Skip to content

Commit d20145c

Browse files
committed
Merge pull request iluwatar#407 from iluwatar/refactor-dao
Solves iluwatar#404 Refactor dao
2 parents d406f0f + 464ae16 commit d20145c

16 files changed

+867
-261
lines changed

dao/etc/dao.png

-172 KB
Loading

dao/etc/dao.ucls

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,71 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<class-diagram version="1.1.8" icons="true" always-add-relationships="false" generalizations="true" realizations="true"
33
associations="true" dependencies="false" nesting-relationships="true">
4-
<class id="1" language="java" name="com.iluwatar.Customer" project="dao"
5-
file="/dao/src/main/java/com/iluwatar/Customer.java" binary="false" corner="BOTTOM_RIGHT">
6-
<position height="-1" width="-1" x="176" y="337"/>
4+
<class id="1" language="java" name="com.iluwatar.dao.App" project="dao"
5+
file="/dao/src/main/java/com/iluwatar/dao/App.java" binary="false" corner="BOTTOM_RIGHT">
6+
<position height="-1" width="-1" x="910" y="191"/>
77
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
88
sort-features="false" accessors="true" visibility="true">
9-
<attributes public="true" package="true" protected="true" private="true" static="true"/>
10-
<operations public="true" package="true" protected="true" private="true" static="true"/>
9+
<attributes public="true" package="true" protected="true" private="false" static="true"/>
10+
<operations public="true" package="true" protected="true" private="false" static="true"/>
1111
</display>
1212
</class>
13-
<class id="2" language="java" name="com.iluwatar.CustomerDaoImpl" project="dao"
14-
file="/dao/src/main/java/com/iluwatar/CustomerDaoImpl.java" binary="false" corner="BOTTOM_RIGHT">
15-
<position height="-1" width="-1" x="540" y="334"/>
13+
<interface id="2" language="java" name="com.iluwatar.dao.CustomerDao" project="dao"
14+
file="/dao/src/main/java/com/iluwatar/dao/CustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
15+
<position height="-1" width="-1" x="536" y="187"/>
1616
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
1717
sort-features="false" accessors="true" visibility="true">
1818
<attributes public="true" package="true" protected="true" private="true" static="true"/>
1919
<operations public="true" package="true" protected="true" private="true" static="true"/>
2020
</display>
21+
</interface>
22+
<class id="3" language="java" name="com.iluwatar.dao.InMemoryCustomerDao" project="dao"
23+
file="/dao/src/main/java/com/iluwatar/dao/InMemoryCustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
24+
<position height="-1" width="-1" x="289" y="455"/>
25+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
26+
sort-features="false" accessors="true" visibility="true">
27+
<attributes public="true" package="true" protected="true" private="false" static="true"/>
28+
<operations public="true" package="true" protected="true" private="true" static="true"/>
29+
</display>
2130
</class>
22-
<interface id="3" language="java" name="com.iluwatar.CustomerDao" project="dao"
23-
file="/dao/src/main/java/com/iluwatar/CustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
24-
<position height="-1" width="-1" x="536" y="131"/>
31+
<class id="4" language="java" name="com.iluwatar.dao.DBCustomerDao" project="dao"
32+
file="/dao/src/main/java/com/iluwatar/dao/DBCustomerDao.java" binary="false" corner="BOTTOM_RIGHT">
33+
<position height="-1" width="-1" x="751" y="456"/>
34+
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
35+
sort-features="false" accessors="true" visibility="true">
36+
<attributes public="true" package="true" protected="true" private="false" static="true"/>
37+
<operations public="true" package="true" protected="true" private="false" static="true"/>
38+
</display>
39+
</class>
40+
<interface id="5" language="java" name="javax.sql.DataSource" project="dao"
41+
file="/opt/Softwares/Eclipses/MARS/eclipse/jre/lib/rt.jar" binary="true" corner="BOTTOM_RIGHT">
42+
<position height="-1" width="-1" x="1083" y="459"/>
2543
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
2644
sort-features="false" accessors="true" visibility="true">
2745
<attributes public="true" package="true" protected="true" private="true" static="true"/>
2846
<operations public="true" package="true" protected="true" private="true" static="true"/>
2947
</display>
3048
</interface>
31-
<realization id="4">
32-
<end type="SOURCE" refId="2"/>
33-
<end type="TARGET" refId="3"/>
34-
</realization>
35-
<association id="5">
36-
<end type="SOURCE" refId="2" navigable="false">
37-
<attribute id="6" name="customers"/>
38-
<multiplicity id="7" minimum="0" maximum="2147483647"/>
49+
<association id="6">
50+
<end type="SOURCE" refId="4" navigable="false">
51+
<attribute id="7" name="dataSource"/>
52+
<multiplicity id="8" minimum="0" maximum="1"/>
3953
</end>
40-
<end type="TARGET" refId="1" navigable="true"/>
54+
<end type="TARGET" refId="5" navigable="true"/>
4155
<display labels="true" multiplicity="true"/>
4256
</association>
57+
<realization id="9">
58+
<end type="SOURCE" refId="3"/>
59+
<end type="TARGET" refId="2"/>
60+
</realization>
61+
<dependency id="10">
62+
<end type="SOURCE" refId="1"/>
63+
<end type="TARGET" refId="2"/>
64+
</dependency>
65+
<realization id="11">
66+
<end type="SOURCE" refId="4"/>
67+
<end type="TARGET" refId="2"/>
68+
</realization>
4369
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
4470
sort-features="false" accessors="true" visibility="true">
4571
<attributes public="true" package="true" protected="true" private="true" static="true"/>

dao/pom.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@
4444
<groupId>log4j</groupId>
4545
<artifactId>log4j</artifactId>
4646
</dependency>
47+
<dependency>
48+
<groupId>com.h2database</groupId>
49+
<artifactId>h2</artifactId>
50+
</dependency>
51+
<dependency>
52+
<groupId>de.bechte.junit</groupId>
53+
<artifactId>junit-hierarchicalcontextrunner</artifactId>
54+
</dependency>
55+
<dependency>
56+
<groupId>org.mockito</groupId>
57+
<artifactId>mockito-core</artifactId>
58+
</dependency>
4759
</dependencies>
4860

4961
<build>

dao/src/main/java/com/iluwatar/dao/App.java

Lines changed: 69 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,49 +20,101 @@
2020
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2121
* THE SOFTWARE.
2222
*/
23+
2324
package com.iluwatar.dao;
2425

26+
import java.sql.Connection;
27+
import java.sql.SQLException;
28+
import java.sql.Statement;
2529
import java.util.ArrayList;
2630
import java.util.List;
31+
import java.util.stream.Stream;
32+
33+
import javax.sql.DataSource;
2734

2835
import org.apache.log4j.Logger;
36+
import org.h2.jdbcx.JdbcDataSource;
2937

3038
/**
31-
*
3239
* Data Access Object (DAO) is an object that provides an abstract interface to some type of
3340
* database or other persistence mechanism. By mapping application calls to the persistence layer,
3441
* DAO provide some specific data operations without exposing details of the database. This
3542
* isolation supports the Single responsibility principle. It separates what data accesses the
3643
* application needs, in terms of domain-specific objects and data types (the public interface of
3744
* the DAO), from how these needs can be satisfied with a specific DBMS.
38-
* <p>
39-
* With the DAO pattern, we can use various method calls to retrieve/add/delete/update data without
40-
* directly interacting with the data. The below example demonstrates basic CRUD operations: select,
41-
* add, update, and delete.
45+
*
46+
* <p>With the DAO pattern, we can use various method calls to retrieve/add/delete/update data
47+
* without directly interacting with the data source. The below example demonstrates basic CRUD
48+
* operations: select, add, update, and delete.
49+
*
4250
*
4351
*/
4452
public class App {
45-
53+
private static final String DB_URL = "jdbc:h2:~/dao:customerdb";
4654
private static Logger log = Logger.getLogger(App.class);
47-
55+
4856
/**
4957
* Program entry point.
5058
*
5159
* @param args command line args.
60+
* @throws Exception if any error occurs.
5261
*/
53-
public static void main(final String[] args) {
54-
final CustomerDao customerDao = new CustomerDaoImpl(generateSampleCustomers());
55-
log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
56-
log.info("customerDao.getCusterById(2): " + customerDao.getCustomerById(2));
62+
public static void main(final String[] args) throws Exception {
63+
final CustomerDao inMemoryDao = new InMemoryCustomerDao();
64+
performOperationsUsing(inMemoryDao);
65+
66+
final DataSource dataSource = createDataSource();
67+
createSchema(dataSource);
68+
final CustomerDao dbDao = new DbCustomerDao(dataSource);
69+
performOperationsUsing(dbDao);
70+
deleteSchema(dataSource);
71+
}
72+
73+
private static void deleteSchema(DataSource dataSource) throws SQLException {
74+
try (Connection connection = dataSource.getConnection();
75+
Statement statement = connection.createStatement()) {
76+
statement.execute(CustomerSchemaSql.DELETE_SCHEMA_SQL);
77+
}
78+
}
79+
80+
private static void createSchema(DataSource dataSource) throws SQLException {
81+
try (Connection connection = dataSource.getConnection();
82+
Statement statement = connection.createStatement()) {
83+
statement.execute(CustomerSchemaSql.CREATE_SCHEMA_SQL);
84+
}
85+
}
86+
87+
private static DataSource createDataSource() {
88+
JdbcDataSource dataSource = new JdbcDataSource();
89+
dataSource.setURL(DB_URL);
90+
return dataSource;
91+
}
92+
93+
private static void performOperationsUsing(final CustomerDao customerDao) throws Exception {
94+
addCustomers(customerDao);
95+
log.info("customerDao.getAllCustomers(): ");
96+
try (Stream<Customer> customerStream = customerDao.getAll()) {
97+
customerStream.forEach((customer) -> log.info(customer));
98+
}
99+
log.info("customerDao.getCustomerById(2): " + customerDao.getById(2));
57100
final Customer customer = new Customer(4, "Dan", "Danson");
58-
customerDao.addCustomer(customer);
59-
log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
101+
customerDao.add(customer);
102+
log.info("customerDao.getAllCustomers(): " + customerDao.getAll());
60103
customer.setFirstName("Daniel");
61104
customer.setLastName("Danielson");
62-
customerDao.updateCustomer(customer);
63-
log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
64-
customerDao.deleteCustomer(customer);
65-
log.info("customerDao.getAllCustomers(): " + customerDao.getAllCustomers());
105+
customerDao.update(customer);
106+
log.info("customerDao.getAllCustomers(): ");
107+
try (Stream<Customer> customerStream = customerDao.getAll()) {
108+
customerStream.forEach((cust) -> log.info(cust));
109+
}
110+
customerDao.delete(customer);
111+
log.info("customerDao.getAllCustomers(): " + customerDao.getAll());
112+
}
113+
114+
private static void addCustomers(CustomerDao customerDao) throws Exception {
115+
for (Customer customer : generateSampleCustomers()) {
116+
customerDao.add(customer);
117+
}
66118
}
67119

68120
/**

dao/src/main/java/com/iluwatar/dao/Customer.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2121
* THE SOFTWARE.
2222
*/
23+
2324
package com.iluwatar.dao;
2425

2526
/**
26-
*
27-
* Customer
27+
* A customer POJO that represents the data that will be read from the data source.
2828
*
2929
*/
3030
public class Customer {
@@ -34,7 +34,7 @@ public class Customer {
3434
private String lastName;
3535

3636
/**
37-
* Constructor
37+
* Creates an instance of customer.
3838
*/
3939
public Customer(final int id, final String firstName, final String lastName) {
4040
this.id = id;
@@ -73,12 +73,12 @@ public String toString() {
7373
}
7474

7575
@Override
76-
public boolean equals(final Object o) {
76+
public boolean equals(final Object that) {
7777
boolean isEqual = false;
78-
if (this == o) {
78+
if (this == that) {
7979
isEqual = true;
80-
} else if (o != null && getClass() == o.getClass()) {
81-
final Customer customer = (Customer) o;
80+
} else if (that != null && getClass() == that.getClass()) {
81+
final Customer customer = (Customer) that;
8282
if (getId() == customer.getId()) {
8383
isEqual = true;
8484
}

dao/src/main/java/com/iluwatar/dao/CustomerDao.java

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,62 @@
2020
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2121
* THE SOFTWARE.
2222
*/
23+
2324
package com.iluwatar.dao;
2425

25-
import java.util.List;
26+
import java.util.Optional;
27+
import java.util.stream.Stream;
2628

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

34-
List<Customer> getAllCustomers();
35-
36-
Customer getCustomerById(int id);
46+
/**
47+
* @return all the customers as a stream. The stream may be lazily or eagerly evaluated based
48+
* on the implementation. The stream must be closed after use.
49+
* @throws Exception if any error occurs.
50+
*/
51+
Stream<Customer> getAll() throws Exception;
52+
53+
/**
54+
* @param id unique identifier of the customer.
55+
* @return an optional with customer if a customer with unique identifier <code>id</code>
56+
* exists, empty optional otherwise.
57+
* @throws Exception if any error occurs.
58+
*/
59+
Optional<Customer> getById(int id) throws Exception;
3760

38-
void addCustomer(Customer customer);
61+
/**
62+
* @param customer the customer to be added.
63+
* @return true if customer is successfully added, false if customer already exists.
64+
* @throws Exception if any error occurs.
65+
*/
66+
boolean add(Customer customer) throws Exception;
3967

40-
void updateCustomer(Customer customer);
68+
/**
69+
* @param customer the customer to be updated.
70+
* @return true if customer exists and is successfully updated, false otherwise.
71+
* @throws Exception if any error occurs.
72+
*/
73+
boolean update(Customer customer) throws Exception;
4174

42-
void deleteCustomer(Customer customer);
75+
/**
76+
* @param customer the customer to be deleted.
77+
* @return true if customer exists and is successfully deleted, false otherwise.
78+
* @throws Exception if any error occurs.
79+
*/
80+
boolean delete(Customer customer) throws Exception;
4381
}

0 commit comments

Comments
 (0)