Skip to content

Commit 4f6e147

Browse files
committed
docs: update dao
1 parent 6cbcf0f commit 4f6e147

File tree

2 files changed

+106
-61
lines changed

2 files changed

+106
-61
lines changed

data-access-object/README.md

Lines changed: 106 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ title: Data Access Object
33
category: Structural
44
language: en
55
tag:
6+
- Abstraction
67
- Data access
8+
- Data processing
9+
- Decoupling
710
- Layered architecture
811
- Persistence
912
---
@@ -21,7 +24,7 @@ The Data Access Object (DAO) design pattern aims to separate the application's b
2124

2225
Real world example
2326

24-
> There's a set of customers that need to be persisted to database. Additionally, we need the whole set of CRUD (create/read/update/delete) operations, so we can operate on customers easily.
27+
> Imagine a library system where the main application manages book loans, user accounts, and inventory. The Data Access Object (DAO) pattern in this context would be used to separate the database operations (such as fetching book details, updating user records, and checking inventory) from the business logic of managing loans and accounts. For instance, there would be a `BookDAO` class responsible for all database interactions related to books, such as retrieving a book by its ISBN or updating its availability status. This abstraction allows the library system's main application code to focus on business rules and workflows, while the `BookDAO` handles the complex SQL queries and data management. This separation makes the system easier to maintain and test, as changes to the data source or business logic can be managed independently.
2528
2629
In plain words
2730

@@ -33,20 +36,22 @@ Wikipedia says
3336
3437
**Programmatic Example**
3538

39+
There's a set of customers that need to be persisted to database. Additionally, we need the whole set of CRUD (create/read/update/delete) operations, so we can operate on customers easily.
40+
3641
Walking through our customers example, here's the basic `Customer` entity.
3742

3843
```java
44+
@Setter
45+
@Getter
46+
@ToString
47+
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
48+
@AllArgsConstructor
3949
public class Customer {
4050

51+
@EqualsAndHashCode.Include
4152
private int id;
4253
private String firstName;
4354
private String lastName;
44-
45-
public Customer(int id, String firstName, String lastName) {
46-
this.id = id;
47-
this.firstName = firstName;
48-
this.lastName = lastName;
49-
}
5055
}
5156
```
5257

@@ -74,16 +79,10 @@ public class InMemoryCustomerDao implements CustomerDao {
7479
}
7580

7681
@Slf4j
82+
@RequiredArgsConstructor
7783
public class DbCustomerDao implements CustomerDao {
7884

79-
private final DataSource
80-
dataSource;
81-
82-
public DbCustomerDao(
83-
DataSource dataSource) {
84-
this.dataSource =
85-
dataSource;
86-
}
85+
private final DataSource dataSource;
8786

8887
// implement the interface using the data source
8988
}
@@ -92,64 +91,111 @@ public class DbCustomerDao implements CustomerDao {
9291
Finally, here's how we use our DAO to manage customers.
9392

9493
```java
95-
final var dataSource=createDataSource();
94+
95+
@Slf4j
96+
public class App {
97+
private static final String DB_URL = "jdbc:h2:mem:dao;DB_CLOSE_DELAY=-1";
98+
private static final String ALL_CUSTOMERS = "customerDao.getAllCustomers(): ";
99+
100+
public static void main(final String[] args) throws Exception {
101+
final var inMemoryDao = new InMemoryCustomerDao();
102+
performOperationsUsing(inMemoryDao);
103+
104+
final var dataSource = createDataSource();
96105
createSchema(dataSource);
97-
final var customerDao=new DbCustomerDao(dataSource);
106+
final var dbDao = new DbCustomerDao(dataSource);
107+
performOperationsUsing(dbDao);
108+
deleteSchema(dataSource);
109+
}
110+
111+
private static void deleteSchema(DataSource dataSource) throws SQLException {
112+
try (var connection = dataSource.getConnection();
113+
var statement = connection.createStatement()) {
114+
statement.execute(CustomerSchemaSql.DELETE_SCHEMA_SQL);
115+
}
116+
}
98117

118+
private static void createSchema(DataSource dataSource) throws SQLException {
119+
try (var connection = dataSource.getConnection();
120+
var statement = connection.createStatement()) {
121+
statement.execute(CustomerSchemaSql.CREATE_SCHEMA_SQL);
122+
}
123+
}
124+
125+
private static DataSource createDataSource() {
126+
var dataSource = new JdbcDataSource();
127+
dataSource.setURL(DB_URL);
128+
return dataSource;
129+
}
130+
131+
private static void performOperationsUsing(final CustomerDao customerDao) throws Exception {
99132
addCustomers(customerDao);
100-
log.info(ALL_CUSTOMERS);
101-
try(var customerStream=customerDao.getAll()){
102-
customerStream.forEach((customer)->log.info(customer.toString()));
133+
LOGGER.info(ALL_CUSTOMERS);
134+
try (var customerStream = customerDao.getAll()) {
135+
customerStream.forEach(customer -> LOGGER.info(customer.toString()));
103136
}
104-
log.info("customerDao.getCustomerById(2): "+customerDao.getById(2));
105-
final var customer=new Customer(4,"Dan","Danson");
137+
LOGGER.info("customerDao.getCustomerById(2): " + customerDao.getById(2));
138+
final var customer = new Customer(4, "Dan", "Danson");
106139
customerDao.add(customer);
107-
log.info(ALL_CUSTOMERS+customerDao.getAll());
140+
LOGGER.info(ALL_CUSTOMERS + customerDao.getAll());
108141
customer.setFirstName("Daniel");
109142
customer.setLastName("Danielson");
110143
customerDao.update(customer);
111-
log.info(ALL_CUSTOMERS);
112-
try(var customerStream=customerDao.getAll()){
113-
customerStream.forEach((cust)->log.info(cust.toString()));
144+
LOGGER.info(ALL_CUSTOMERS);
145+
try (var customerStream = customerDao.getAll()) {
146+
customerStream.forEach(cust -> LOGGER.info(cust.toString()));
114147
}
115148
customerDao.delete(customer);
116-
log.info(ALL_CUSTOMERS+customerDao.getAll());
149+
LOGGER.info(ALL_CUSTOMERS + customerDao.getAll());
150+
}
117151

118-
deleteSchema(dataSource);
152+
private static void addCustomers(CustomerDao customerDao) throws Exception {
153+
for (var customer : generateSampleCustomers()) {
154+
customerDao.add(customer);
155+
}
156+
}
157+
158+
public static List<Customer> generateSampleCustomers() {
159+
final var customer1 = new Customer(1, "Adam", "Adamson");
160+
final var customer2 = new Customer(2, "Bob", "Bobson");
161+
final var customer3 = new Customer(3, "Carl", "Carlson");
162+
return List.of(customer1, customer2, customer3);
163+
}
164+
}
119165
```
120166

121167
The program output:
122168

123-
```java
124-
customerDao.getAllCustomers():
125-
Customer{id=1,firstName='Adam',lastName='Adamson'}
126-
Customer{id=2,firstName='Bob',lastName='Bobson'}
127-
Customer{id=3,firstName='Carl',lastName='Carlson'}
128-
customerDao.getCustomerById(2):Optional[Customer{id=2,firstName='Bob',lastName='Bobson'}]
129-
customerDao.getAllCustomers():java.util.stream.ReferencePipeline$Head@7cef4e59
130-
customerDao.getAllCustomers():
131-
Customer{id=1,firstName='Adam',lastName='Adamson'}
132-
Customer{id=2,firstName='Bob',lastName='Bobson'}
133-
Customer{id=3,firstName='Carl',lastName='Carlson'}
134-
Customer{id=4,firstName='Daniel',lastName='Danielson'}
135-
customerDao.getAllCustomers():java.util.stream.ReferencePipeline$Head@2db0f6b2
136-
customerDao.getAllCustomers():
137-
Customer{id=1,firstName='Adam',lastName='Adamson'}
138-
Customer{id=2,firstName='Bob',lastName='Bobson'}
139-
Customer{id=3,firstName='Carl',lastName='Carlson'}
140-
customerDao.getCustomerById(2):Optional[Customer{id=2,firstName='Bob',lastName='Bobson'}]
141-
customerDao.getAllCustomers():java.util.stream.ReferencePipeline$Head@12c8a2c0
142-
customerDao.getAllCustomers():
143-
Customer{id=1,firstName='Adam',lastName='Adamson'}
144-
Customer{id=2,firstName='Bob',lastName='Bobson'}
145-
Customer{id=3,firstName='Carl',lastName='Carlson'}
146-
Customer{id=4,firstName='Daniel',lastName='Danielson'}
147-
customerDao.getAllCustomers():java.util.stream.ReferencePipeline$Head@6ec8211c
169+
```
170+
10:02:09.788 [main] INFO com.iluwatar.dao.App -- customerDao.getAllCustomers():
171+
10:02:09.793 [main] INFO com.iluwatar.dao.App -- Customer(id=1, firstName=Adam, lastName=Adamson)
172+
10:02:09.793 [main] INFO com.iluwatar.dao.App -- Customer(id=2, firstName=Bob, lastName=Bobson)
173+
10:02:09.793 [main] INFO com.iluwatar.dao.App -- Customer(id=3, firstName=Carl, lastName=Carlson)
174+
10:02:09.794 [main] INFO com.iluwatar.dao.App -- customerDao.getCustomerById(2): Optional[Customer(id=2, firstName=Bob, lastName=Bobson)]
175+
10:02:09.794 [main] INFO com.iluwatar.dao.App -- customerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@4c3e4790
176+
10:02:09.794 [main] INFO com.iluwatar.dao.App -- customerDao.getAllCustomers():
177+
10:02:09.795 [main] INFO com.iluwatar.dao.App -- Customer(id=1, firstName=Adam, lastName=Adamson)
178+
10:02:09.795 [main] INFO com.iluwatar.dao.App -- Customer(id=2, firstName=Bob, lastName=Bobson)
179+
10:02:09.795 [main] INFO com.iluwatar.dao.App -- Customer(id=3, firstName=Carl, lastName=Carlson)
180+
10:02:09.795 [main] INFO com.iluwatar.dao.App -- Customer(id=4, firstName=Daniel, lastName=Danielson)
181+
10:02:09.795 [main] INFO com.iluwatar.dao.App -- customerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@5679c6c6
182+
10:02:09.894 [main] INFO com.iluwatar.dao.App -- customerDao.getAllCustomers():
183+
10:02:09.895 [main] INFO com.iluwatar.dao.App -- Customer(id=1, firstName=Adam, lastName=Adamson)
184+
10:02:09.895 [main] INFO com.iluwatar.dao.App -- Customer(id=2, firstName=Bob, lastName=Bobson)
185+
10:02:09.895 [main] INFO com.iluwatar.dao.App -- Customer(id=3, firstName=Carl, lastName=Carlson)
186+
10:02:09.895 [main] INFO com.iluwatar.dao.App -- customerDao.getCustomerById(2): Optional[Customer(id=2, firstName=Bob, lastName=Bobson)]
187+
10:02:09.896 [main] INFO com.iluwatar.dao.App -- customerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@23282c25
188+
10:02:09.897 [main] INFO com.iluwatar.dao.App -- customerDao.getAllCustomers():
189+
10:02:09.897 [main] INFO com.iluwatar.dao.App -- Customer(id=1, firstName=Adam, lastName=Adamson)
190+
10:02:09.897 [main] INFO com.iluwatar.dao.App -- Customer(id=2, firstName=Bob, lastName=Bobson)
191+
10:02:09.898 [main] INFO com.iluwatar.dao.App -- Customer(id=3, firstName=Carl, lastName=Carlson)
192+
10:02:09.898 [main] INFO com.iluwatar.dao.App -- Customer(id=4, firstName=Daniel, lastName=Danielson)
193+
10:02:09.898 [main] INFO com.iluwatar.dao.App -- customerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@f2f2cc1
148194
```
149195

150196
## Class diagram
151197

152-
![alt text](./etc/dao.png "Data Access Object")
198+
![Data Access Object](./etc/dao.png "Data Access Object")
153199

154200
## Applicability
155201

@@ -161,8 +207,8 @@ Use the Data Access Object in any of the following situations:
161207

162208
## Tutorials
163209

164-
* [The DAO Pattern in Java](https://www.baeldung.com/java-dao-pattern)
165-
* [Data Access Object Pattern](https://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm)
210+
* [The DAO Pattern in Java(Baeldung)](https://www.baeldung.com/java-dao-pattern)
211+
* [Data Access Object Pattern (TutorialsPoint)](https://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm)
166212

167213
## Known Uses
168214

@@ -187,15 +233,15 @@ Trade-offs:
187233

188234
## Related Patterns
189235

190-
* [Service Layer](https://java-design-patterns.com/patterns/service-layer/): Often used in conjunction with the DAO pattern to define application's boundaries and its set of available operations.
191-
* [Factory](https://java-design-patterns.com/patterns/factory/): Can be used to instantiate DAOs dynamically, providing flexibility in the choice of implementation.
192236
* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): Helps in abstracting the creation of DAOs, especially when supporting multiple databases or storage mechanisms.
237+
* [Factory](https://java-design-patterns.com/patterns/factory/): Can be used to instantiate DAOs dynamically, providing flexibility in the choice of implementation.
238+
* [Service Layer](https://java-design-patterns.com/patterns/service-layer/): Often used in conjunction with the DAO pattern to define application's boundaries and its set of available operations.
193239
* [Strategy](https://java-design-patterns.com/patterns/strategy/): Might be employed to change the data access strategy at runtime, depending on the context.
194240

195241
## Credits
196242

197-
* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=48d37c67fb3d845b802fa9b619ad8f31)
198243
* [Core J2EE Patterns: Best Practices and Design Strategies](https://amzn.to/49u3r91)
199-
* [Patterns of Enterprise Application Architecture](https://amzn.to/3U5cxEI)
200244
* [Expert One-on-One J2EE Design and Development](https://amzn.to/3vK3pfq)
245+
* [J2EE Design Patterns](https://amzn.to/4dpzgmx)
246+
* [Patterns of Enterprise Application Architecture](https://amzn.to/3U5cxEI)
201247
* [Professional Java Development with the Spring Framework](https://amzn.to/49tANF0)

data-access-object/src/main/java/com/iluwatar/dao/Customer.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,4 @@ public class Customer {
4444
private int id;
4545
private String firstName;
4646
private String lastName;
47-
4847
}

0 commit comments

Comments
 (0)