将规范转换为查询谓词

时间:2010-12-28 16:56:12

标签: java jpa domain-driven-design specifications

我正试图找到一种基于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存储库实现可以通过依赖注入使用我的管理器来提供按规范方法查找。按规范提供find应该会大大减少我们的存储库接口上的方法数量。

从理论上讲,这听起来不错,但我觉得我错过了一些关键的东西。你们对我的建议有什么看法,它是否符合DDD的思维方式?或者是否已经有一个与我刚刚描述的相同的框架?

3 个答案:

答案 0 :(得分:1)

Hades是一个Repository框架,作为JPA的包装器。它是DDD友好的。它支持开箱即用的DDD Specifications。我还建议您查看InfoQ中的这篇文章。

答案 1 :(得分:0)

  

我实际上读过那篇文章,但是hades规范要求你在你的文章中加入JPA逻辑   规格。规格是特定领域的,应与任何类型的产品分开   持久性逻辑。

JPA注释男人怎么样?您认为您的域对象应该与JPA注释分开吗?

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

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

答案 2 :(得分:-2)

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