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

时间:2012-09-24 13:23:52

标签: java design-patterns java-ee dao dto

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

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

  1. 使用一个参数搜索,另一个
  2. 使用多个参数进行搜索
  3. 不带参数搜索。
  4. 我的问题是,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";
    }
    

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

1 个答案:

答案 0 :(得分:6)

我通常倾向于创建一个基本的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)。