【问题标题】:translating specifications into query predicates将规范转换为查询谓词
【发布时间】:2010-12-28 16:56:12
【问题描述】:

我正在尝试找到一种基于 DDD“规范”查询数据库内容的好方法。

在域驱动设计中,规范用于检查某个对象(也称为候选对象)是否符合(特定于域的)要求。例如,规范“IsTaskDone”如下所示:

class IsTaskDone extends Specification<Task> {
 boolean isSatisfiedBy(Task candidate) {
  return candidate.isDone();
 }
}

上述规范可用于多种用途,例如它可用于验证任务是否已完成,或从集合中过滤所有已完成的任务。 但是,我想重新使用这个很好的领域相关规范来查询数据库。

当然,最简单的解决方案是从数据库中检索我们所需类型的所有实体,并通过循环和删除不匹配的实体来过滤内存中的列表。但显然这对于​​性能来说并不是最优的,尤其是当我们数据库中的实体数量增加时。

建议

所以我的想法是创建一个“ConversionManager”,将我的规范转换为持久性技术特定标准,想想 JPA 谓词类。服务如下:

public interface JpaSpecificationConversionManager {
 <T> Predicate getPredicateFor(Specification<T> specification, Root<T> root, CriteriaQuery<?> cq, CriteriaBuilder cb);
 JpaSpecificationConversionManager registerConverter(JpaSpecificationConverter<?, ?> converter);
}

通过使用我们的管理器,用户可以注册自己的转换逻辑,将领域相关规范与持久性特定逻辑隔离开来。为了最小化我们的管理器的配置,我想在我的转换器类上使用注释,允许管理器自动注册这些转换器。

JPA 存储库实现然后可以通过依赖注入使用我的管理器来提供按规范查找的方法。按规范提供查找应该会大大减少我们存储库接口上的方法数量。

理论上,这一切听起来都不错,但我觉得我错过了一些关键的东西。大家觉得我的提议怎么样,符合DDD的思路吗?或者是否已经有一个框架可以做与我刚才描述的相同的事情?

【问题讨论】:

  • 人们想知道为什么 Java 会因为过度设计而受到不好的包装......
  • 当您有规范的合取(逻辑与)时,您如何处理这种情况?如何将规范的结合转化为查询?

标签: java jpa domain-driven-design specifications


【解决方案1】:

Hades 是一个存储库框架,作为 JPA 的包装器。它对 DDD 友好。它开箱即用地支持 DDD Specifications。我也建议你看看这篇来自InfoQ的文章。

【讨论】:

  • 我确实读过那篇文章,但是 hades 规范要求您在规范中包含 JPA 逻辑。规范是特定领域的,应该与任何类型的持久性逻辑分开。
  • 正确。 DDD Quickly 一书中有一节说,将一些与业务相关的逻辑与实际查询分开是比较困难的,即不将其与数据库相关的东西联系起来。然而,它也提供了一个简单的解决方案。在这里下载本书:infoq.com/news/2006/12/domain-driven-design
  • 介意给我那个解决方案的页码吗?我所能找到的只是使用具有特定于域的访问方法的存储库。我宁愿使用规范的主要原因是保持我的存储库的接口小。
  • 对不起!如果那本书中没有,它可能在 DDD 圣经中:domaindrivendesign.org/books/evans_2003
【解决方案2】:

我实际上读过那篇文章,但是 hades 规范要求您在您的 规格。规范是特定领域的,应该与任何类型的 持久化逻辑。

JPA 注释人呢...?您认为您的域对象应该与 JPA 注释分开吗?

我认为 Hades 提供的解决方案(现在称为“spring-data-jpa”)比 Evans 书中提供的解决方案更好:Eric Evans 展示了一个示例,其中“规范”调用“存储库”本身就叫做“规范”!我真的很想知道客户端代码如何只通过规范,而不直接使用存储库。 Hades/Spring-data-jpa提供的方案对我来说很好,把JPA放到领域逻辑里面就可以了,因为JPA是设计进领域层的。

编辑:我忘了提到 Eric Evans 实现了“双重调度”,这不是规范和存储库之间的愚蠢循环依赖,但如上所述,它不会阻止任何开发人员绕过规范实现。

【讨论】:

    【解决方案3】:

    在 .NET 世界中,LINQ 涵盖了这一点。我知道没有 Java 等价物。

    【讨论】:

    • Querydsl 是 Java 世界中最接近 linq 的东西。结合 spring data 和 java 8 stream api,非常接近。
    猜你喜欢
    • 2014-08-04
    • 2021-10-21
    • 2019-12-25
    • 2016-09-20
    • 2020-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多