Skip to content

Commit 1e1c20e

Browse files
committed
test: Add unit test dao-factory
1 parent c854664 commit 1e1c20e

22 files changed

+1364
-352
lines changed

dao-factory/README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
## Also known as
2+
3+
4+
5+
## Intent of Data Access Object Factory Design Pattern
6+
7+
8+
## Detailed Explanation of Data Access Object Factory Pattern with Real-World Examples
9+
10+
Class diagram
11+
12+
![Data Access Object Factory class diagram](./etc/dao-factory.png "Data Access Object Factory class diagram")
13+
14+
## Programmatic Example of Data Access Object Factory in Java
15+
16+
## When to Use the Data Access Object Factory Pattern in Java
17+
18+
## Data Access Object Factory Pattern Java Tutorials
19+
20+
21+
## Benefits and Trade-offs of Data Access Object Factory Pattern
22+
23+
## Real-World Applications of Data Access Object Factory Pattern in Java
24+
25+
## Related Java Design Patterns
26+
27+
## References and Credits

dao-factory/etc/dao-factory.puml

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
@startuml
2+
package com.iluwatar.daofactory {
3+
class App {
4+
{static} void main(String[] args)
5+
{static} <T> void performCreateCustomer(CustomerDAO<T> customerDAO, \n List<Customer<T>> customerList)
6+
{static} <T> void performUpdateCustomer(CustomerDAO<T> customerDAO, \n Customer<T> customerUpdate)
7+
{static} <T> void performDeleteCustomer(CustomerDAO<T> customerDAO, \n T id)
8+
{static} void deleteSchema(CustomerDAO customerDAO)
9+
}
10+
11+
class Customer<T> {
12+
T id
13+
String name
14+
}
15+
16+
interface CustomerDAO<ID> {
17+
void save(Customer<ID> customer)
18+
void update(Customer<ID> customer)
19+
void delete(ID id)
20+
List<Customer<ID>> findAll()
21+
Optional<Customer<ID>> findById(ID id)
22+
void deleteSchema()
23+
}
24+
25+
abstract class DAOFactory {
26+
{static} DAOFactory getDataSource(DataSourceType dataType)
27+
{abstract} CustomerDAO createCustomerDAO()
28+
}
29+
30+
enum DataSourceType {
31+
H2
32+
Mongo
33+
FlatFile
34+
}
35+
36+
class FlatFileCustomerDAO implements CustomerDAO<Long> {
37+
void save(Customer<Long> customer)
38+
void update(Customer<Long> customer)
39+
void delete(Long id)
40+
List<Customer<Long>> findAll()
41+
Optional<Customer<Long>> findById(Long id)
42+
void deleteSchema()
43+
}
44+
45+
class H2CustomerDAO implements CustomerDAO<Long> {
46+
void save(Customer<Long> customer)
47+
void update(Customer<Long> customer)
48+
void delete(Long id)
49+
List<Customer<Long>> findAll()
50+
Optional<Customer<Long>> findById(Long id)
51+
void deleteSchema()
52+
}
53+
54+
class FlatFileDataSourceFactory extends DAOFactory {
55+
CustomerDAO createCustomerDAO()
56+
}
57+
58+
class H2DataSourceFactory extends DAOFactory {
59+
CustomerDAO createCustomerDAO()
60+
}
61+
62+
class MongoCustomerDAO implements CustomerDAO<ObjectId> {
63+
void save(Customer<ObjectId> customer)
64+
void update(Customer<ObjectId> customer)
65+
void delete(ObjectId id)
66+
List<Customer<ObjectId>> findAll()
67+
Optional<Customer<ObjectId>> findById(ObjectId id)
68+
void deleteSchema()
69+
}
70+
class MongoDataSourceFactory extends DAOFactory {
71+
CustomerDAO createCustomerDAO()
72+
}
73+
74+
DataSourceType ..+ DAOFactory
75+
DAOFactory ..+ App
76+
App --> Customer
77+
}
78+
@enduml

dao-factory/pom.xml

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@
3131
<groupId>ch.qos.logback</groupId>
3232
<artifactId>logback-classic</artifactId>
3333
</dependency>
34-
<dependency>
35-
<groupId>org.mongodb</groupId>
36-
<artifactId>bson</artifactId>
37-
</dependency>
34+
<!-- <dependency>-->
35+
<!-- <groupId>org.mongodb</groupId>-->
36+
<!-- <artifactId>bson</artifactId>-->
37+
<!-- </dependency>-->
3838
<dependency>
3939
<groupId>org.mongodb</groupId>
4040
<artifactId>mongodb-driver-legacy</artifactId>
@@ -43,6 +43,18 @@
4343
<groupId>com.google.code.gson</groupId>
4444
<artifactId>gson</artifactId>
4545
</dependency>
46+
47+
<dependency>
48+
<groupId>org.junit.jupiter</groupId>
49+
<artifactId>junit-jupiter-engine</artifactId>
50+
<scope>test</scope>
51+
</dependency>
52+
53+
<dependency>
54+
<groupId>org.mockito</groupId>
55+
<artifactId>mockito-core</artifactId>
56+
<scope>test</scope>
57+
</dependency>
4658
</dependencies>
4759

4860
</project>

dao-factory/src/main/java/com/iluwatar/daofactory/App.java

Lines changed: 37 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,109 +1,99 @@
11
package com.iluwatar.daofactory;
22

3-
import java.sql.SQLException;
43
import java.util.List;
54
import lombok.extern.slf4j.Slf4j;
65
import org.bson.types.ObjectId;
7-
import org.slf4j.Logger;
8-
import org.slf4j.LoggerFactory;
96

10-
/**
11-
* Created by: IntelliJ IDEA
12-
* User : dthanh
13-
* Date : 16/04/2025
14-
* Time : 23:08
15-
* Filename : ${NAME}
16-
*/
177
@Slf4j
188
public class App {
199

20-
private static final Logger logger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
2110

22-
23-
24-
public static void main(String[] args) throws SQLException {
25-
final var h2DAO = DAOFactory.getDataSource(DataSourceEnum.H2);
26-
final var mongoDAO = DAOFactory.getDataSource(DataSourceEnum.Mongo);
27-
final var flatFileDAO = DAOFactory.getDataSource(DataSourceEnum.FlatFile);
28-
29-
final var h2CustomerDAO = h2DAO.getCustomerDAO();
30-
final var mongoCustomerDAO = mongoDAO.getCustomerDAO();
31-
final var flatFileCustomerDAO = flatFileDAO.getCustomerDAO();
11+
public static void main(String[] args) {
12+
var daoFactory = DAOFactory.getDataSource(DataSourceType.H2);
13+
var customerDAO = daoFactory.createCustomerDAO();
3214

3315
// Perform CRUD H2 Database
16+
if (customerDAO instanceof H2CustomerDAO h2CustomerDAO) {
17+
h2CustomerDAO.deleteSchema();
18+
h2CustomerDAO.createSchema();
19+
}
3420
Customer<Long> customerInmemory1 = new Customer<>(1L, "Green");
3521
Customer<Long> customerInmemory2 = new Customer<>(2L, "Red");
3622
Customer<Long> customerInmemory3 = new Customer<>(3L, "Blue");
3723
Customer<Long> customerUpdateInmemory = new Customer<>(1L, "Yellow");
3824

3925
LOGGER.debug("H2 - Create customer");
40-
performCreateCustomer(h2CustomerDAO,
26+
performCreateCustomer(customerDAO,
4127
List.of(customerInmemory1, customerInmemory2, customerInmemory3));
4228
LOGGER.debug("H2 - Update customer");
43-
performUpdateCustomer(h2CustomerDAO, customerUpdateInmemory);
29+
performUpdateCustomer(customerDAO, customerUpdateInmemory);
4430
LOGGER.debug("H2 - Delete customer");
45-
performDeleteCustomer(h2CustomerDAO, 3L);
46-
deleteSchema(h2CustomerDAO);
31+
performDeleteCustomer(customerDAO, 3L);
32+
deleteSchema(customerDAO);
4733

4834
// Perform CRUD MongoDb
35+
daoFactory = DAOFactory.getDataSource(DataSourceType.Mongo);
36+
customerDAO = daoFactory.createCustomerDAO();
4937
ObjectId idCustomerMongo1 = new ObjectId();
5038
ObjectId idCustomerMongo2 = new ObjectId();
5139
Customer<ObjectId> customer4 = new Customer<>(idCustomerMongo1, "Masca");
5240
Customer<ObjectId> customer5 = new Customer<>(idCustomerMongo2, "Elliot");
5341
Customer<ObjectId> customerUpdateMongo = new Customer<>(idCustomerMongo2, "Henry");
5442

5543
LOGGER.debug("Mongo - Create customer");
56-
performCreateCustomer(mongoCustomerDAO, List.of(customer4, customer5));
44+
performCreateCustomer(customerDAO, List.of(customer4, customer5));
5745
LOGGER.debug("Mongo - Update customer");
58-
performUpdateCustomer(mongoCustomerDAO, customerUpdateMongo);
46+
performUpdateCustomer(customerDAO, customerUpdateMongo);
5947
LOGGER.debug("Mongo - Delete customer");
60-
performDeleteCustomer(mongoCustomerDAO, idCustomerMongo2);
61-
deleteSchema(mongoCustomerDAO);
48+
performDeleteCustomer(customerDAO, idCustomerMongo2);
49+
deleteSchema(customerDAO);
6250

6351
// Perform CRUD Flat file
52+
daoFactory = DAOFactory.getDataSource(DataSourceType.FlatFile);
53+
customerDAO = daoFactory.createCustomerDAO();
6454
Customer<Long> customerFlatFile1 = new Customer<>(1L, "Duc");
6555
Customer<Long> customerFlatFile2 = new Customer<>(2L, "Quang");
6656
Customer<Long> customerFlatFile3 = new Customer<>(3L, "Nhat");
6757
Customer<Long> customerUpdateFlatFile = new Customer<>(1L, "Thanh");
6858
LOGGER.debug("Flat file - Create customer");
69-
performCreateCustomer(flatFileCustomerDAO,
59+
performCreateCustomer(customerDAO,
7060
List.of(customerFlatFile1, customerFlatFile2, customerFlatFile3));
7161
LOGGER.debug("Flat file - Update customer");
72-
performUpdateCustomer(flatFileCustomerDAO, customerUpdateFlatFile);
62+
performUpdateCustomer(customerDAO, customerUpdateFlatFile);
7363
LOGGER.debug("Flat file - Delete customer");
74-
performDeleteCustomer(flatFileCustomerDAO, 3L);
75-
deleteSchema(flatFileCustomerDAO);
64+
performDeleteCustomer(customerDAO, 3L);
65+
deleteSchema(customerDAO);
7666
}
7767

7868
public static void deleteSchema(CustomerDAO<?> customerDAO) {
7969
customerDAO.deleteSchema();
8070
}
8171

82-
public static <ID> void performCreateCustomer(CustomerDAO<ID> customerDAO,
83-
List<Customer<ID>> customerList) {
84-
for (Customer<ID> customer : customerList) {
72+
public static <T> void performCreateCustomer(CustomerDAO<T> customerDAO,
73+
List<Customer<T>> customerList) {
74+
for (Customer<T> customer : customerList) {
8575
customerDAO.save(customer);
8676
}
87-
List<Customer<ID>> customers = customerDAO.findAll();
88-
for (Customer<ID> customer : customers) {
77+
List<Customer<T>> customers = customerDAO.findAll();
78+
for (Customer<T> customer : customers) {
8979
LOGGER.debug(customer.toString());
9080
}
9181
}
9282

93-
public static <ID> void performUpdateCustomer(CustomerDAO<ID> customerDAO,
94-
Customer<ID> customerUpdate) {
83+
public static <T> void performUpdateCustomer(CustomerDAO<T> customerDAO,
84+
Customer<T> customerUpdate) {
9585
customerDAO.update(customerUpdate);
96-
List<Customer<ID>> customers = customerDAO.findAll();
97-
for (Customer<ID> customer : customers) {
98-
LOGGER.error(customer.toString());
86+
List<Customer<T>> customers = customerDAO.findAll();
87+
for (Customer<T> customer : customers) {
88+
LOGGER.debug(customer.toString());
9989
}
10090
}
10191

102-
public static <ID> void performDeleteCustomer(CustomerDAO<ID> customerDAO,
103-
ID customerId) {
92+
public static <T> void performDeleteCustomer(CustomerDAO<T> customerDAO,
93+
T customerId) {
10494
customerDAO.delete(customerId);
105-
List<Customer<ID>> customers = customerDAO.findAll();
106-
for (Customer<ID> customer : customers) {
95+
List<Customer<T>> customers = customerDAO.findAll();
96+
for (Customer<T> customer : customers) {
10797
LOGGER.debug(customer.toString());
10898
}
10999
}

dao-factory/src/main/java/com/iluwatar/daofactory/Customer.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@
88
import lombok.ToString;
99

1010
/**
11-
* Created by: IntelliJ IDEA
12-
* User : dthanh
13-
* Date : 16/04/2025
14-
* Time : 23:22
15-
* Filename : Customer
11+
* A customer generic POJO that represents the data that can be stored in any supported data source.
12+
* This class is designed t work with various ID types (e.g., Long, String, or ObjectId) through generic,
13+
* making it adaptable to different persistence system.
1614
*/
1715
@Getter
1816
@Setter

dao-factory/src/main/java/com/iluwatar/daofactory/CustomerDAO.java

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,57 @@
44
import java.util.Optional;
55

66
/**
7-
* Created by: IntelliJ IDEA
8-
* User : dthanh
9-
* Date : 16/04/2025
10-
* Time : 23:16
11-
* Filename : CustomerDAO
7+
* The Data Access Object (DAO) pattern provides an abstraction layer between the application
8+
* and the database. It encapsulates data access logic, allowing the application to work
9+
* with domain objects instead of direct database operations.
10+
*
11+
* <p>Implementations handle specific storage mechanisms (e.g., in-memory, databases)
12+
* while keeping client code unchanged.
13+
*
14+
* @see H2CustomerDAO
15+
* @see MongoCustomerDAO
16+
* @see FlatFileCustomerDAO
1217
*/
13-
public interface CustomerDAO<ID> {
14-
void save(Customer<ID> customer);
18+
public interface CustomerDAO<T> {
19+
/**
20+
* Persist the given customer
21+
*
22+
* @param customer the customer to persist
23+
*/
24+
void save(Customer<T> customer);
1525

16-
void update(Customer<ID> customer);
26+
/**
27+
* Update the given customer
28+
*
29+
* @param customer the customer to update
30+
*/
31+
void update(Customer<T> customer);
1732

18-
void delete(ID id);
33+
/**
34+
* Delete the customer with the given id
35+
*
36+
* @param id the id of the customer to delete
37+
*/
38+
void delete(T id);
1939

20-
List<Customer<ID>> findAll();
40+
/**
41+
* Find all customers
42+
*
43+
* @return a list of customers
44+
*/
45+
List<Customer<T>> findAll();
2146

22-
Optional<Customer<ID>> findById(ID id);
47+
/**
48+
* Find the customer with the given id
49+
*
50+
* @param id the id of the customer to find
51+
* @return the customer with the given id
52+
*/
53+
Optional<Customer<T>> findById(T id);
2354

55+
/**
56+
* Delete the customer schema. After executing the statements,
57+
* this function will be called to clean up the data and delete the records.
58+
*/
2459
void deleteSchema();
2560
}

0 commit comments

Comments
 (0)