* add state and callback pattern * add command and template-method pattern * add iterator pattern * add bridege and DI pattern * fix issue #1600 * add converter,proxy,visitor pattern * add caching,composite,delegation,dirty-flag,interpreter patterns * add dao and producer-consumer * add dto and provate class data pattern * fix #1646 png path problems * fix #1646 composite png path case problem * add abstract document pattern and version-number pattern * add ambassador pattern * add acyclic-visitor and api-gateway pattern * add abstract-factory pattern * add active-object pattern * add aggregator-microservices and arrange-act-assert pattern * update async-method-invocation pattern * add balking and business-delegate pattern * add bytecode and circuit-break pattern * update arrange/act/assert pattern problems * add csch pattern * add language code, correct pic path * #1805 update permalink Co-authored-by: Subhrodip Mohanta <subhrodipmohanta@gmail.com> Co-authored-by: Mike <admin@xiaod.info> Co-authored-by: Ilkka Seppälä <iluwatar@users.noreply.github.com>
		
			
				
	
	
	
		
			4.9 KiB
		
	
	
	
	
	
	
	
			
		
		
	
	
			4.9 KiB
		
	
	
	
	
	
	
	
layout, title, folder, permalink, categories, language, tags
| layout | title | folder | permalink | categories | language | tags | |
|---|---|---|---|---|---|---|---|
| pattern | Data Access Object | dao | /patterns/dao/ | Architectural | zh | 
 | 
目的
对象为某种类型的数据库或其他持久性机制提供了抽象接口。
解释
真实世界例子
有一组客户数据需要持久化到数据库中。 我们需要整个额外的增删改查操作以便操作客户数据。
通俗的说
DAO是我们通过基本持久性机制提供的接口。
维基百科说
在计算机软件中,数据访问对象(DAO)是一种模式,可为某种类型的数据库或其他持久性机制提供抽象接口。
程序示例
通过我们的客户示例,下面是基本的客户实体。
public class Customer {
  private int id;
  private String firstName;
  private String lastName;
  public Customer(int id, String firstName, String lastName) {
    this.id = id;
    this.firstName = firstName;
    this.lastName = lastName;
  }
  // getters and setters ->
  ...
}
这是CustomerDao接口及其两个不同的实现。
Here's the CustomerDao interface and two different implementations for it. InMemoryCustomerDao
将简单的客户数据映射保存在内存中 而DBCustomerDao是真正的RDBMS实现。
public interface CustomerDao {
  Stream<Customer> getAll() throws Exception;
  Optional<Customer> getById(int id) throws Exception;
  boolean add(Customer customer) throws Exception;
  boolean update(Customer customer) throws Exception;
  boolean delete(Customer customer) throws Exception;
}
public class InMemoryCustomerDao implements CustomerDao {
  private final Map<Integer, Customer> idToCustomer = new HashMap<>();
  // implement the interface using the map
  ...
}
public class DbCustomerDao implements CustomerDao {
  private static final Logger LOGGER = LoggerFactory.getLogger(DbCustomerDao.class);
  private final DataSource dataSource;
  public DbCustomerDao(DataSource dataSource) {
    this.dataSource = dataSource;
  }
  // implement the interface using the data source
  ...
最后,这是我们使用DAO管理客户数据的方式。
    final var dataSource = createDataSource();
    createSchema(dataSource);
    final var customerDao = new DbCustomerDao(dataSource);
    
    addCustomers(customerDao);
    log.info(ALL_CUSTOMERS);
    try (var customerStream = customerDao.getAll()) {
      customerStream.forEach((customer) -> log.info(customer.toString()));
    }
    log.info("customerDao.getCustomerById(2): " + customerDao.getById(2));
    final var customer = new Customer(4, "Dan", "Danson");
    customerDao.add(customer);
    log.info(ALL_CUSTOMERS + customerDao.getAll());
    customer.setFirstName("Daniel");
    customer.setLastName("Danielson");
    customerDao.update(customer);
    log.info(ALL_CUSTOMERS);
    try (var customerStream = customerDao.getAll()) {
      customerStream.forEach((cust) -> log.info(cust.toString()));
    }
    customerDao.delete(customer);
    log.info(ALL_CUSTOMERS + customerDao.getAll());
    
    deleteSchema(dataSource);
程序输出:
customerDao.getAllCustomers(): 
Customer{id=1, firstName='Adam', lastName='Adamson'}
Customer{id=2, firstName='Bob', lastName='Bobson'}
Customer{id=3, firstName='Carl', lastName='Carlson'}
customerDao.getCustomerById(2): Optional[Customer{id=2, firstName='Bob', lastName='Bobson'}]
customerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@7cef4e59
customerDao.getAllCustomers(): 
Customer{id=1, firstName='Adam', lastName='Adamson'}
Customer{id=2, firstName='Bob', lastName='Bobson'}
Customer{id=3, firstName='Carl', lastName='Carlson'}
Customer{id=4, firstName='Daniel', lastName='Danielson'}
customerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@2db0f6b2
customerDao.getAllCustomers(): 
Customer{id=1, firstName='Adam', lastName='Adamson'}
Customer{id=2, firstName='Bob', lastName='Bobson'}
Customer{id=3, firstName='Carl', lastName='Carlson'}
customerDao.getCustomerById(2): Optional[Customer{id=2, firstName='Bob', lastName='Bobson'}]
customerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@12c8a2c0
customerDao.getAllCustomers(): 
Customer{id=1, firstName='Adam', lastName='Adamson'}
Customer{id=2, firstName='Bob', lastName='Bobson'}
Customer{id=3, firstName='Carl', lastName='Carlson'}
Customer{id=4, firstName='Daniel', lastName='Danielson'}
customerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@6ec8211c
类图
适用性
在以下情况下,请使用数据访问对象::
- 当您要巩固如何访问数据层时。
- 当您要避免编写多个数据检索/持久层时。
