11

假设,我决定为我的企业应用程序使用 Java EE 堆栈。

现在,对于域建模(或:用于设计 MVC 的 M),我可以安全地假设和使用哪些 API,以及我应该远离哪些……比如说,通过抽象层?

例如,

  1. 我应该继续调用 Hibernate/JPA API 来乱扔我的模型吗?或者,我应该构建一个抽象......一个我自己的持久层以避免对这两个特定的持久性 API 进行硬编码?为什么我要问这个:几年前,这个 Kodo API 被 Hibernate 取代了。如果设计了一个持久层并针对该层对模型的其余部分进行编码(而不是通过调用特定的供应商 API 来乱扔模型),它将允许一个人(相对)轻松地从 Kodo 切换到 Hibernate 再到 xyz。

  2. 是否建议在域模型中积极使用持久性供应商提供的 *QL?我不知道由于大量使用类似 HQL 的语言而引起的任何实际问题(如性能、可伸缩性、可移植性等)。为什么问这个问题:我想尽可能避免编写自定义代码,因为这可以通过比 SQL 更便携的查询语言来完成。

对不起,但我是这个领域的新手。我在哪里可以找到有关此主题的更多信息?

4

2 回答 2

8

以下是我认为的传统观点:

  • 项目中的实体构成域模型。它们应该是可重用的,而不是与持久性技术紧密耦合(稍后我将讨论紧耦合与松耦合)
  • 业务层,使用领域模型,但也暴露服务和其他东西。
  • 数据访问层负责将域模型(实体)持久存储在持久存储中。

实体不应直接调用数据访问层。但是业务层将以某种方式加载和持久化领域模型的实体。

如果您将其映射到 Java EE 技术,您通常会得到如下信息:

  • 实体 --> 带有 Hibernate/JPA 注释的 POJO。请注意,注释并不意味着与 JPA/Hibernate 紧密耦合,相同的 POJO 可以在没有 Hibernate 的其他地方使用。
  • 业务层 --> Session EJB 或 Spring
  • 数据访问层 --> JPA/Hibernate

这是一个粗略的草图,有很多可能的变体。您可以明显地跳过会话 EJB 并以另一种方式实现业务层。您还可以决定让业务层直接调用 JPA/Hibernate Session/EntityManager,在这种情况下 JPA/Hibernate 确实是 DAL,或者您可能希望将 Session/EntityManager 的访问包装到所谓的数据访问对象(DAO )。

关于 HQL,尽量坚持什么是可移植的,如果您使用原生 SQL,请遵循 SQL-92 约定。如果事情变得复杂,也许可以引入 DAO。这样,您就知道唯一存在 HQL 查询的地方就是 DAO。你也可以先在DAO中“程序化”实现查询逻辑,如果遇到性能问题,再用更复杂的HQL查询重新实现。

编辑

关于评论中的问题:

业务层依赖于数据层。如果您希望业务层不依赖于 Hibernate/JPA,那么您的数据层需要将Hibernate/JPA抽象出来。如果您将 DAO 用于数据层,情况就是如此。DAO 将是“Hibernate 上的薄手写持久层”(用你的话来说)。在您的案例中,我将为所有实体介绍 DAO。

您要问的是一个非常通用的设计问题。我无法为此给出明确的配方,也无法在一个答案中总结所有变体,因为这取决于具体情况。例如,到目前为止,我们还没有谈到事务问题,您通常从业务层开始,但数据层必须意识到这一点。这通常取决于所使用的技术和您的要求。

不过,这里是您可能感兴趣的资源列表:书籍Pattern of Enterprise Application Architecture、书籍Real World Java EE Patterns - Rethinking Best Practices、书籍Domain Driven Design以及更具体的模式Data Access ObjectRepository patternOpen Session in View(如果它用于 Web 应用程序),也许还有Anemic Domain Model

编辑 2

好的,关于交易的更多句子:

事务在概念上应该在业务层进行管理;一个工作单元中需要做什么才能保持一致的定义确实取决于应用程序的逻辑。

使用 EJB3,可以使用注释和应用程序声明事务。服务器为您管理。有关更多信息,请参阅我的其他答案。使用 Spring,您还可以以声明方式标记事务,但我不知道细节。否则,您将需要自己启动/停止交易。无论您使用 JDBC 事务还是 JTA 事务,这都会略有不同。

事务还与 Hibernate/JPA 中的延迟加载有关。延迟加载的实体确实只有在存在当前事务时才能加载。如果事务在业务层中终止,则返回到表示层的实体需要预先加载。

To circumvent this problem, a popular pattern for web applications is Open Session in View, which I already mentioned. In this case, the presentation layer start/stop the transactions (which is slightly wrong conceptually), but works just fine with lazy loading.

于 2010-04-14T07:39:06.487 回答
4

你的域模型和它的持久层理论上应该是分开的 - 不需要调用一个类Entity来知道它是否以及如何持久化,所以你可以使用像 Hibernate 这样的东西来创建持久层而不污染域模型类本身. 您不会“针对该层对 [...] 模型进行编码” - 您对模型进行编码,然后将其映射到具有某种 ORM 层的持久存储,其中域模型不依赖于 ORM 层。显然持久层将依赖于领域模型,但这很好。

出于您问的原因,我个人避免在 (N)Hibernate 中使用过多的 HQL,但有时这是不可避免的。您已经知道并强调了那里的主要问题,因此无论如何您都不太可能过度使用它。

于 2010-04-14T06:40:57.847 回答