Java EE DAO / DTO(数据传输对象)设计模式

Posted

技术标签:

【中文标题】Java EE DAO / DTO(数据传输对象)设计模式【英文标题】:Java EE DAO / DTO (Data Transfer Object) Design Patterns 【发布时间】:2012-09-15 23:14:30 【问题描述】:

目前我正在为我的工作项目使用 struts2 框架,在设计我的 DAO 类时,我有一个问题要改进设计模式。

在我的搜索功能上,我有 3 种搜索

    用一个参数搜索,另一个参数, 使用多个参数进行搜索, 不带参数搜索。

我的问题是,执行 DAO 方法的最佳方法是什么?

在我的 struts2 方法中,我有

public String execute() 

    //assuming these are passed in from JSP
    if ("searchByAnId".equals(paramSearch))
    
        List<DTO> datalist = this.someDao.implementList(theIdParam);

     else if("searchByAnOtherParam".equals(paramSearch))
    
        List<DTO> datalist = this.someDao.implementAnotherList(param1, param2, param3, param4)
        // more params
     else
    
        List<DTO> datalist = this.someDao.implementListAll();
           

    return "success";

我正在阅读诸如工厂方法、装饰器方法、观察者方法之类的设计模式,但我不确定哪一个是最合适的(或其他没有 3rd 方插件的)适合这个?

【问题讨论】:

在我的项目中,我创建了一个 SearchCriteria 对象,其中包含 DAO 所属表的列。然后,您在此 SearchCriteria 对象中提供详细信息,并在您的 DAO 中根据它进行搜索。 是的,我不认为有任何特定的设计模式。 【参考方案1】:

我通常倾向于创建一个基本的 dao 接口,其中定义了我所有域实体共有的方法,例如:

// marker interface
public interface DomainEntity extends Serializable  

// common dao methods
public interface DAO<T extends DomainEntity> 
  public T findById(Long id);
  public List<T> findAll();
  public T save(T entity);
  public boolean update(T entity);
  public boolean delete(T entity);

然后根据我的要求提供一个或多个实现:

// implementation of common dao methods using JPA
public class JpaDAO<T> implements DAO<T> 

    private EntityManager em;

    public JpaDao(EntityManager em)  this.em = em; 

   // Default implementations using JPA...


// implementation of common dao methods using JDBC
public class JdbcDAO<T> implements DAO<T> 

  private Connection conn;

  public JdbcDao(Connection conn)  this.conn = conn; 

  // Default implementations using JDBC

现在,假设我有以下人员类:

public class Person implements DomainEntity 
  private Long id;
  private String firstName;
  private String lastName;

  // getters/setters...

我首先像这样定义一个通用的 PersonDAO 接口:

public interface PersonDAO implements DAO<Person> 
  public List<Person> findByFirstName(String name);
  public List<Person> findByLastName(String name);

请注意,在我上面的特定实体 dao 接口中,我只包含了特定于我的域实体的额外方法。通用方法由超级接口继承,并使用泛型参数化为我的域实体。

现在剩下的最后一件事是定义我的实体特定方法的不同实现,如下所示:

package mypackage.daos.jpa;

public class PersonDAOImpl extends JpaDAO<Person> implements PersonDAO 
   // here i implement only the entity specific dao methods 
   // defined in the last interface.

如果我还需要提供替代的 DAO 实现(比如基于 jdbc 而不是 JPA),它就像创建第二个类一样简单(最好在单独的包中):

package mypackage.daos.jdbc;

public class PersonDAOImpl extends JdbcDAO<Person> implements PersonDAO 
  // again i only implement the entity specific DAO methods since
  // defaults have been implemented in the super class...

这样做的好处是您可以在没有调用代码的情况下切换实现:

// a service class that uses my dao
public class PersonService 

  private PersonDAO dao;

  public PersonService(PersonDAO dao)  this.dao = dao 

  public void doSomethingUseful() 
     // use the dao here...
  

通常,正确的 dao 实现(jdbc 或 jpa)将在服务创建期间通过构造函数注入。当然,如果你愿意,你只能有一个实现(即 jpa)。

【讨论】:

所以确认一下,“interface PersonDAO”和“DAO”之间的关系是什么?抱歉,我的设计模式很糟糕...... Interface DAO 是一个类型参数化的接口,它定义了所有域实体通用的 DAO 操作。接口 PersonDAO(扩展 DAO)包括特定于 Person 域实体的操作。 关于通用 PersonDao - 不应该是 interface PersonDao extends Dao&lt;Person&gt; 而不是 implements

以上是关于Java EE DAO / DTO(数据传输对象)设计模式的主要内容,如果未能解决你的问题,请参考以下文章

java的几种对象(po,dto,dao等)

J2EE基本概念

java的几种对象(PO,VO,DAO,BO,POJO,DTO)解释

java的几种对象(PO,VO,DAO,BO,POJO,DTO)解释

java的几种对象(PO,VO,DAO,BO,POJO,DTO)解释

Java中DAO/DTO/PO/VO/BO/QO/POJO