【问题标题】:I found JPA, or alike, don't encourage DAO pattern我发现 JPA 或类似的,不鼓励 DAO 模式
【发布时间】:2011-01-07 04:36:34
【问题描述】:

我发现 JPA 或类似的,不鼓励 DAO 模式。我不知道,但我有这种感觉,尤其是对于服务器管理的 JTA 管理器。

在使用 DAO 模式进行了充分的实践之后,我开始围绕该模式设计基于 JPA 的应用程序。但它不适合,IMO。我倾向于失去 JPA 的相当多的功能和所有功能。

好吧,假设您使用悲观锁定触发一个查询,并从 DAO 方法返回一个实体列表。返回后,事务结束并且锁定消失(服务器管理的 JTA 管理器的情况)。所以,没有意义,松散地说。不过,也有有效的案例。

另一个例子要简单得多。假设您触发查询以获取某个实体,该实体与其他实体具有延迟加载一对多关联。返回 DAO 方法后,事务结束。延迟加载不再起作用,您只需获得null 或其他东西。为了解决这个问题,我们急切地手动加载它。我们会做类似a.getBList().size() 的事情。

因此,IMO 最好不要专门创建 DAO,而是在您的业务 bean 中进行,这样您就可以利用这些有用的功能。或者 ORM API 可以被认为是一个 DAO/数据层本身,可以说。所以,我们不需要再做一个了。

大家怎么看?

注意:无论如何,我并不是说 DAO 模式已经过时。事实上,这取决于具体情况。

【问题讨论】:

    标签: java hibernate orm jpa dao


    【解决方案1】:

    对于简单的应用程序,我认为直接从 EJB 使用 EntityManager 并跳过 DAO 模式没有任何问题(我厌倦了编写太多代码)。我的感觉确实是 JPA 和 Java EE API 所鼓励的。但是对于更复杂的应用程序(对于从存储过程、平面文件...进行数据访问)来说,它仍然是合理的。所以你是对的,这取决于:)

    您会在 InfoQ 上的 Has JPA Killed the DAO? 中找到其他一些开明的观点,但您不会对内容和结论感到惊讶,可以概括为:您不再需要 DAO 模式作为标准数据访问,但是在一些更复杂的情况下您可能需要它,但没有它我们生活得更好。

    【讨论】:

    • (+1) 我倾向于同意,如果一个人没有什么特别的想法,就没有理由创建一个 dao 层。即使是一个通用的 DAO,更不用说一个单独的实体 DAO 类了。
    • 我一直在努力寻找一种测试我的 Java EE JAX-RS/JPA 代码的好方法,而试图获得一个可行的“测试中的容器”解决方案是一场噩梦。主要方面是尝试从测试中注入一个@Context PersistenceContext。我在想,使用 @EJB Dao 以及从测试中调用并设置 Dao 的构造函数将是干净的。
    【解决方案2】:

    如果您不将 DAO 本身定义为事务性的,那么您将不会遇到这些问题。

    服务层应该是事务性的,因为一个事务应该跨越多个操作。将每个插入/更新放入事务中并不是最好的方案。

    使用 spring,您可以轻松实现这一目标。如果没有它,您可能会再次在您的 DAO 中包含事务逻辑 - 即 dao.beginTransaction() 和 dao.commitTransaction() 并从服务层使用它。

    据我了解,您建议直接在服务类中使用 EntityManager 可能比使用包装器 DAO 类更好。我不同意,原因之一。在您的服务类中使用 DAO 类(最好是接口),您根本不依赖 JPA API。您不必构造 Query 对象或类似的东西。这可能不是一个很大的优势,但你会同意这是一个最佳实践。以后只需更改 DAO,您就可以切换到纯 JDBC、纯文本、XML 或其他任何东西。

    这虽然被广泛用作为什么应该在另一层中抽象某些东西的示例,但通常只是过度设计。但有时,您的所有数据库访问操作都经过一个地方这一事实意味着您可以添加日志记录、访问级别检查等(是的,有时 DAO 并不是一种特别合适的方式)。

    所以最终,回到你的观点 - 这取决于。

    【讨论】:

    • “在您的服务类中使用 DAO 类 (...),您根本不依赖 JPA API。” 好的,如果您不这样做t 这样做你依赖于 EJB 3 - 但那又怎样?说真的,有什么问题?我不在乎依赖于标准 API。
    • 当然,您仍然依赖于它,因为您使用它,这没有问题。但我的观点是,您无需修改​​所有类即可轻松更改持久性机制,因为它们仅依赖于 DAO 接口。
    • @Bozho 我完全理解你的意思,但我在 10 年内没有看到这种情况经常发生,并认为这件事是一种神话。
    • +1,绝对正确。即使在 JPA 环境中,DAO 模式仍然相关,因为您的服务层是事务性的,一个事务可以跨越多个 DAO 调用。
    • me neighter :) 但也可以添加日志记录、访问检查等。现在 DAO 并不是这样做的最佳场所。所以最终 - 这取决于:)
    【解决方案3】:

    DAO 用于设计透视图,而 JPA 是数据访问功能的一些“官方”包装器。 JPA 没有办法试图扼杀 DAO——它可以使 DAO 更易于实现,也许如此简单以至于 DAO 看起来如此简单以至于可以忽略。但如果没有 DAO 层,设计优势将不复存在。

    当然,对于“简单”的项目,可以忽略。如果项目足够“简单”,很多事情都可以“忽略”。

    【讨论】:

    • Elton:我完全同意你的意思,没有任何如果和但是。然而,我想强调的是,分层并不是获得好的设计的唯一手段。因此,我不能完全同意你的这种说法,“没有层意味着所有的设计利益都不再存在”。我希望你明白我的意思。
    • 好的。道层长期存在是有原因的。它确实带来了设计上的好处。如果没有 dao 层,这些设计优势肯定会消失。也许在你的情况下你不在乎这就是为什么你觉得它已经过时了。我认为你的问题实际上是关于道带来了什么,而是你是否需要道带来的。对我来说,“道”层从未消失过。当您将 EntityManager 注入您的业务层时,您的业务层也在做 Dao 层的工作。您出于自己的原因将这些层组合在一起。对于您的情况,这可能是更好的解决方案。一次又一次,这取决于,没有“绝对”
    • Elton:请注意,即使在您到达这里之前,结论也是一样的,即“视情况而定”。我从来没有觉得DAO是一个过时的模式,请仔细阅读问题。我试图让这一点非常明显。
    • 是的,我之所以添加我的评论是为了多加一点,JPA 是功能性的,而 DAO 是设计视角。虽然我没有明确地说“依赖”,但我是在用另一种方式说“依赖”。我想我没有反对任何人。
    • +1 在架构上将 DAO 称为包装器。 DAO 是包装与数据库接口的 API 的层。这可能是具有一些 ORM 优势的 JPA (EntityManager),也可能只是 JDBC。
    猜你喜欢
    • 1970-01-01
    • 2019-08-22
    • 2014-02-03
    • 2014-04-30
    • 2011-10-23
    • 2010-11-09
    • 2015-06-14
    • 1970-01-01
    相关资源
    最近更新 更多