【问题标题】:Adding business logic to JPA entities向 JPA 实体添加业务逻辑
【发布时间】:2021-02-14 12:21:04
【问题描述】:

在下一个场景中,我必须将一些带有 JPA 规范的静态过滤器(添加 WHERE 子句)应用于 JPA 实体以获取过滤的狗列表,例如,我从一个实体收到一个 id,我必须申请相同的过滤器,但为每个未完成的过滤器发送错误消息。例如:拥有实体 Dog,我收到一个 id,使用 JPA 获取此实体并应用一些过滤器,例如狗年龄>3 年等...

我的想法是重用 JPA 规范以执行此操作,但使用它们不会向我提供有关为什么我没有获取实体以及未完成哪个过滤器以发送错误消息的信息。

我所做的是将 isDogOlderThan3Years() 之类的方法添加到 JPA 实体中,并且实体本身会为每个过滤器请求其属性等。我认为这与非贫血实体有关。这是一个好/坏的解决方案吗?有没有更好的?

谢谢

【问题讨论】:

  • 您似乎正在尝试查找 3 岁以上的狗的列表。如果是这种情况,这只是一个查询,不应成为您的域模型的一部分。
  • 但我的意思是使用多个过滤器,而不仅仅是一个

标签: jpa domain-driven-design anemic-domain-model


【解决方案1】:

我认为specification pattern 在这里可能很有用。

您可以使用 Visitor pattern 将规范组合转换为 JPA 查询,并且您可以实现上述文章中讨论的 remainderUnsatisfied 操作,以找出给定候选人不符合哪些条件。

如果不关心关注点分离,可以直接在规范上实现toJpaFilterdescribe等方法 .

我在我的一个项目中使用了这种方法,我设法重用相同的规范来执行以下操作,并且效果很好:

  • 定义复杂的访问控制规则和过滤器
  • 定义和执行业务规则
  • 生成用户友好的规范描述

【讨论】:

  • 为什么不向 JPA 实体添加像 isDogOlderThan3Years() 这样的 @Transients 方法?就是 DDD 所说的富模型,对吧?
  • @user3254515 富模型并不意味着将所有职责放在一个实体中。如果所有谓词逻辑都在实体本身内,规范也会丰富您的模型,并且会更加灵活。
  • 好的,所以关于“你可以实现剩余不满足操作”,我可以创建一个名为 DogOlderThan3YearsSpecification 的类,它接收一个 Dog 作为参数并返回布尔值。此方法的实现将询问 Dog 对象的年龄。这个想法对吗?这样您就不必修改 JPA 实体(不违反 OPEN/CLOSE 原则),并且对于更多未来的规范,您应该创建一个新的规范,对吧?
  • 是的。不过,我不会那么具体,保持规范更开放,例如DogOlderThan,然后您可以指定时间范围。例如。 new DogOlderThan(Duration.ofYears(3))。然后可以实现AndSpecOrSpec等复合规范,组合成更复杂的规范。
  • 完美!。你会为这些自定义规范类分配什么包?
猜你喜欢
  • 2013-06-16
  • 1970-01-01
  • 1970-01-01
  • 2017-12-17
  • 1970-01-01
  • 2011-04-15
  • 2012-09-16
  • 2013-11-29
  • 2013-09-14
相关资源
最近更新 更多