2

上次我使用 JBoss 7.1(Java EE6 标准)开发应用程序时,我使用 DAO 编写了持久层。

首先,我有一个“抽象”DAO,它是所有具体 daos 之父:

public abstract class AbstractDao<T> {

    private Class<T> entityClass;

    private String defaultSortColumn;

    public AbstractDao(Class<T> entityClass) {
        this.entityClass = entityClass;
        this.defaultSortColumn = "";
    }

    protected abstract EntityManager getEntityManager();

    public void create(T entity) {
        getEntityManager().persist(entity);
    }

    public void edit(T entity) {
        getEntityManager().merge(entity);
    }

    public void remove(T entity) {
        getEntityManager().remove(getEntityManager().merge(entity));
    }

    public T find(Object id) {
        return getEntityManager().find(entityClass, id);
    }

    @SuppressWarnings("rawtypes")
    public List<T> find() {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
    CriteriaQuery cq = cb.createQuery();
        Root from = cq.from(entityClass);
        cq.select(from);
        return getEntityManager().createQuery(cq).getResultList();
    }

    @SuppressWarnings("rawtypes")
    public int count() {
        //...
    }

}

然后我为我的域中的每个数据库实体都有一个 dao 实现。

它们彼此都非常相似,它们只是为查询添加了比通常的“crud”操作更复杂的方法。

这是一个例子:

@Stateless
public class ShopDao extends AbstractDao<Shop> {

    @Inject
    private EntityManager em;

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    public ShopDao() {
        super(Shop.class);
    }
}

如您所见,我的 DAO 是无状态 EJB。

这种方式使我的应用程序工作,但是......当我必须创建一个新实体时,我必须同时创建实体本身和 DAO。是不是有点多余?但是,我想不出更好的方法,因为我经常需要对特定实体进行复杂的查询。

问题是:

  • 这是最佳做法吗?我还能如何设计我的持久层?

  • DAO 成为 EJB 好不好?

  • 我在客户端(JSF 控制器)进行了验证。它应该在持久层吗?如何?

  • 将原始 EntityManager 放在服务层类中会更好吗,避免 DAO?

编辑

有没有办法避免每张桌子都有一个道?

4

3 回答 3

4

“这是最佳实践吗?我还能如何设计我的持久层?”

你的方法似乎还可以。有些人喜欢让 DAO 层完全独立于其他层。这种方法的优点是您可以在其他地方重用 DAO 层,并且在应用程序服务器之外测试您的 DAO 也更容易。我不太提倡这种方法,因为它通常是一种矫枉过正的做法——EJB 方法只是 DAO 层的薄包装。EJB 也很容易在应用程序服务器之外进行测试(Spring 提供了所有需要的测试工具)。因此,只要您不打算在 EJB 中实现更复杂的业务逻辑,我就会采用您的方法。

请阅读以获得更多详情...

“DAO 成为 EJB 好不好?”

更准确地说,EJB 在您的方法中不是 DAO,因为它们还管理事务,可以负责其他非数据库的业务逻辑元素。EJB 还为您的应用程序提供外部接口。从技术上讲,EntityManager 是您的 DAO,EJB 正在使用它来实现所有需要的业务逻辑。

“我在客户端(JSF 控制器)进行了验证。它应该在持久层中吗?如何?”

在 Java EE 6 中,您可以利用 Bean 验证技术 - 您在模型级别定义验证规则(作为实体字段上的注释),这些规则由持久层和 JSF Web 层强制执行。

“在服务层类中使用原始 EntityManager 会更好,避免 DAO 吗?”

据我了解,您想摆脱 EJB 吗?你可以这样做,但是你需要自己管理事务(在简单的情况下没什么大不了的)。无状态本地接口或无接口 EJB 目前非常轻量级,因此没有充分的理由避免使用它们。作为替代,您可以使用 Spring Framework 对 JPA 的支持。

于 2013-04-16T20:04:11.820 回答
2

我建议完全放弃 DAO。你必须问自己,你需要它们做什么?

1st) 抽象 DAO 类实际上什么都不做,然后将调用委托给实体管理器,因此您为自己创建了一个edit替换 的方法merge,这不仅没有必要,而且使您的代码更难阅读,因为有人必须检查,什么你的edit方法可以。

2nd)你没有展示具体的 DAO 类做了什么,但很可能这可以在实体本身中完成(因为实体是一个业务对象,而不仅仅是一个哑数据容器)或在控制器中(因为它们控制实体之间的交互,例如作为无状态 EJB)。

始终从简单的应用程序开始,不要从设计可能需要一些时间的层开始,但现在会使一切变得更加复杂。

于 2013-04-22T06:30:13.447 回答
-1

部分答案:

我认为这是一个很好的做法,但就我而言,我也会有一个包含部分逻辑的实体服务层。通常我使用一个隐藏dao的EntityService,它负责逻辑/验证/...

但是如果你使用 spring,你可以(应该?)使用spring-data-jpa,它有一个非常好的数据层。

不要将验证嵌入到持久层中。保留此层仅用于数据库访问。例如,验证应在服务层中完成(或根据您的项目在视图层中)。并将实体管理器保留在持久层中,因为它们是粘在一起的。

于 2013-04-16T15:54:39.437 回答