Skip to content

Commit

Permalink
Merge pull request #407 from iluwatar/refactor-dao
Browse files Browse the repository at this point in the history
Solves #404 Refactor dao
  • Loading branch information
iluwatar committed Mar 28, 2016
2 parents d406f0f + 464ae16 commit d20145c
Show file tree
Hide file tree
Showing 16 changed files with 867 additions and 261 deletions.
Binary file modified dao/etc/dao.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 46 additions & 20 deletions dao/etc/dao.ucls
Original file line number Diff line number Diff line change
@@ -1,45 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<class-diagram version="1.1.8" icons="true" always-add-relationships="false" generalizations="true" realizations="true"
associations="true" dependencies="false" nesting-relationships="true">
<class id="1" language="java" name="com.iluwatar.Customer" project="dao"
file="/dao/src/main/java/com/iluwatar/Customer.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="176" y="337"/>
<class id="1" language="java" name="com.iluwatar.dao.App" project="dao"
file="/dao/src/main/java/com/iluwatar/dao/App.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="910" y="191"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
<attributes public="true" package="true" protected="true" private="false" static="true"/>
<operations public="true" package="true" protected="true" private="false" static="true"/>
</display>
</class>
<class id="2" language="java" name="com.iluwatar.CustomerDaoImpl" project="dao"
file="/dao/src/main/java/com/iluwatar/CustomerDaoImpl.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="540" y="334"/>
<interface id="2" language="java" name="com.iluwatar.dao.CustomerDao" project="dao"
file="/dao/src/main/java/com/iluwatar/dao/CustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="536" y="187"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</interface>
<class id="3" language="java" name="com.iluwatar.dao.InMemoryCustomerDao" project="dao"
file="/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="289" y="455"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="false" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</class>
<interface id="3" language="java" name="com.iluwatar.CustomerDao" project="dao"
file="/dao/src/main/java/com/iluwatar/CustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="536" y="131"/>
<class id="4" language="java" name="com.iluwatar.dao.DBCustomerDao" project="dao"
file="/dao/src/main/java/com/iluwatar/dao/DBCustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="751" y="456"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="false" static="true"/>
<operations public="true" package="true" protected="true" private="false" static="true"/>
</display>
</class>
<interface id="5" language="java" name="javax.sql.DataSource" project="dao"
file="/opt/Softwares/Eclipses/MARS/eclipse/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="1083" y="459"/>
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
<operations public="true" package="true" protected="true" private="true" static="true"/>
</display>
</interface>
<realization id="4">
<end type="SOURCE" refId="2"/>
<end type="TARGET" refId="3"/>
</realization>
<association id="5">
<end type="SOURCE" refId="2" navigable="false">
<attribute id="6" name="customers"/>
<multiplicity id="7" minimum="0" maximum="2147483647"/>
<association id="6">
<end type="SOURCE" refId="4" navigable="false">
<attribute id="7" name="dataSource"/>
<multiplicity id="8" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="1" navigable="true"/>
<end type="TARGET" refId="5" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<realization id="9">
<end type="SOURCE" refId="3"/>
<end type="TARGET" refId="2"/>
</realization>
<dependency id="10">
<end type="SOURCE" refId="1"/>
<end type="TARGET" refId="2"/>
</dependency>
<realization id="11">
<end type="SOURCE" refId="4"/>
<end type="TARGET" refId="2"/>
</realization>
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
sort-features="false" accessors="true" visibility="true">
<attributes public="true" package="true" protected="true" private="true" static="true"/>
Expand Down
12 changes: 12 additions & 0 deletions dao/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>de.bechte.junit</groupId>
<artifactId>junit-hierarchicalcontextrunner</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
86 changes: 69 additions & 17 deletions dao/src/main/java/com/iluwatar/dao/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,49 +20,101 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package com.iluwatar.dao;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.h2.jdbcx.JdbcDataSource;

/**
*
* Data Access Object (DAO) is an object that provides an abstract interface to some type of
* database or other persistence mechanism. By mapping application calls to the persistence layer,
* DAO provide some specific data operations without exposing details of the database. This
* isolation supports the Single responsibility principle. It separates what data accesses the
* application needs, in terms of domain-specific objects and data types (the public interface of
* the DAO), from how these needs can be satisfied with a specific DBMS.
* <p>
* With the DAO pattern, we can use various method calls to retrieve/add/delete/update data without
* directly interacting with the data. The below example demonstrates basic CRUD operations: select,
* add, update, and delete.
*
* <p>With the DAO pattern, we can use various method calls to retrieve/add/delete/update data
* without directly interacting with the data source. The below example demonstrates basic CRUD
* operations: select, add, update, and delete.
*
*
*/
public class App {

private static final String DB_URL = "jdbc:h2:~/dao:customerdb";
private static Logger log = Logger.getLogger(App.class);

/**
* Program entry point.
*
* @param args command line args.
* @throws Exception if any error occurs.
*/
public static void main(final String[] args) {
final CustomerDao customerDao = new CustomerDaoImpl(generateSampleCustomers());
log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
log.info("customerDao.getCusterById(2): " + customerDao.getCustomerById(2));
public static void main(final String[] args) throws Exception {
final CustomerDao inMemoryDao = new InMemoryCustomerDao();
performOperationsUsing(inMemoryDao);

final DataSource dataSource = createDataSource();
createSchema(dataSource);
final CustomerDao dbDao = new DbCustomerDao(dataSource);
performOperationsUsing(dbDao);
deleteSchema(dataSource);
}

private static void deleteSchema(DataSource dataSource) throws SQLException {
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement()) {
statement.execute(CustomerSchemaSql.DELETE_SCHEMA_SQL);
}
}

private static void createSchema(DataSource dataSource) throws SQLException {
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement()) {
statement.execute(CustomerSchemaSql.CREATE_SCHEMA_SQL);
}
}

private static DataSource createDataSource() {
JdbcDataSource dataSource = new JdbcDataSource();
dataSource.setURL(DB_URL);
return dataSource;
}

private static void performOperationsUsing(final CustomerDao customerDao) throws Exception {
addCustomers(customerDao);
log.info("customerDao.getAllCustomers(): ");
try (Stream<Customer> customerStream = customerDao.getAll()) {
customerStream.forEach((customer) -> log.info(customer));
}
log.info("customerDao.getCustomerById(2): " + customerDao.getById(2));
final Customer customer = new Customer(4, "Dan", "Danson");
customerDao.addCustomer(customer);
log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
customerDao.add(customer);
log.info("customerDao.getAllCustomers(): " + customerDao.getAll());
customer.setFirstName("Daniel");
customer.setLastName("Danielson");
customerDao.updateCustomer(customer);
log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
customerDao.deleteCustomer(customer);
log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
customerDao.update(customer);
log.info("customerDao.getAllCustomers(): ");
try (Stream<Customer> customerStream = customerDao.getAll()) {
customerStream.forEach((cust) -> log.info(cust));
}
customerDao.delete(customer);
log.info("customerDao.getAllCustomers(): " + customerDao.getAll());
}

private static void addCustomers(CustomerDao customerDao) throws Exception {
for (Customer customer : generateSampleCustomers()) {
customerDao.add(customer);
}
}

/**
Expand Down
14 changes: 7 additions & 7 deletions dao/src/main/java/com/iluwatar/dao/Customer.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package com.iluwatar.dao;

/**
*
* Customer
* A customer POJO that represents the data that will be read from the data source.
*
*/
public class Customer {
Expand All @@ -34,7 +34,7 @@ public class Customer {
private String lastName;

/**
* Constructor
* Creates an instance of customer.
*/
public Customer(final int id, final String firstName, final String lastName) {
this.id = id;
Expand Down Expand Up @@ -73,12 +73,12 @@ public String toString() {
}

@Override
public boolean equals(final Object o) {
public boolean equals(final Object that) {
boolean isEqual = false;
if (this == o) {
if (this == that) {
isEqual = true;
} else if (o != null && getClass() == o.getClass()) {
final Customer customer = (Customer) o;
} else if (that != null && getClass() == that.getClass()) {
final Customer customer = (Customer) that;
if (getId() == customer.getId()) {
isEqual = true;
}
Expand Down
56 changes: 47 additions & 9 deletions dao/src/main/java/com/iluwatar/dao/CustomerDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,62 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package com.iluwatar.dao;

import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

/**
* In an application the Data Access Object (DAO) is a part of Data access layer. It is an object
* that provides an interface to some type of persistence mechanism. By mapping application calls
* to the persistence layer, DAO provides some specific data operations without exposing details
* of the database. This isolation supports the Single responsibility principle. It separates what
* data accesses the application needs, in terms of domain-specific objects and data types
* (the public interface of the DAO), from how these needs can be satisfied with a specific DBMS,
* database schema, etc.
*
* CustomerDao
*
* <p>Any change in the way data is stored and retrieved will not change the client code as the
* client will be using interface and need not worry about exact source.
*
* @see InMemoryCustomerDao
* @see DbCustomerDao
*/
public interface CustomerDao {

List<Customer> getAllCustomers();

Customer getCustomerById(int id);
/**
* @return all the customers as a stream. The stream may be lazily or eagerly evaluated based
* on the implementation. The stream must be closed after use.
* @throws Exception if any error occurs.
*/
Stream<Customer> getAll() throws Exception;

/**
* @param id unique identifier of the customer.
* @return an optional with customer if a customer with unique identifier <code>id</code>
* exists, empty optional otherwise.
* @throws Exception if any error occurs.
*/
Optional<Customer> getById(int id) throws Exception;

void addCustomer(Customer customer);
/**
* @param customer the customer to be added.
* @return true if customer is successfully added, false if customer already exists.
* @throws Exception if any error occurs.
*/
boolean add(Customer customer) throws Exception;

void updateCustomer(Customer customer);
/**
* @param customer the customer to be updated.
* @return true if customer exists and is successfully updated, false otherwise.
* @throws Exception if any error occurs.
*/
boolean update(Customer customer) throws Exception;

void deleteCustomer(Customer customer);
/**
* @param customer the customer to be deleted.
* @return true if customer exists and is successfully deleted, false otherwise.
* @throws Exception if any error occurs.
*/
boolean delete(Customer customer) throws Exception;
}
Loading

0 comments on commit d20145c

Please sign in to comment.