简体   繁体   English

将规范转换为查询谓词

[英]translating specifications into query predicates

I'm trying to find a nice and elegant way to query database content based on DDD "specifications". 我试图找到一种基于DDD“规范”查询数据库内容的好方法。

In domain driven design, a specification is used to check if some object, also known as the candidate, is compliant to a (domain specific) requirement. 在域驱动设计中,使用规范来检查某个对象(也称为候选对象)是否符合(特定于域的)要求。 For example, the specification 'IsTaskDone' goes like: 例如,规范“ IsTaskDone”如下所示:

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

The above specification can be used for many purposes, eg it can be used to validate if a task has been completed, or to filter all completed tasks from a collection. 上面的规范可用于许多目的,例如,可用于验证任务是否已完成,或从集合中筛选出所有已完成的任务。 However, I want to re-use this, nice, domain related specification to query on the database. 但是,我想重用这个很好的,与领域相关的规范来查询数据库。

Of course, the easiest solution would be to retrieve all entities of our desired type from the database, and filter that list in-memory by looping and removing non-matching entities. 当然,最简单的解决方案是从数据库中检索所需类型的所有实体,然后通过循环并删除不匹配的实体来过滤内存中的列表。 But clearly that would not be optimal for performance, especially when the entity count in our db increases. 但是显然,这对于性能而言不是最佳的,尤其是当数据库中的实体数量增加时。

Proposal 提案

So my idea is to create a 'ConversionManager' that translates my specification into a persistence technique specific criteria, think of the JPA predicate class. 因此,我的想法是创建一个“ ConversionManager”,将我的规范转换为特定于持久性技术的标准,考虑一下JPA谓词类。 The services looks as follows: 服务如下所示:

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

By using our manager, the users can register their own conversion logic, isolating the domain related specification from persistence specific logic. 通过使用我们的管理器,用户可以注册自己的转换逻辑,从而将与域相关的规范与持久性特定的逻辑隔离开。 To minimize the configuration of our manager, I want to use annotations on my converter classes, allowing the manager to automatically register those converters. 为了最大程度地减少管理器的配置,我想在转换器类上使用批注,以允许管理器自动注册这些转换器。

JPA repository implementations could then use my manager, via dependency injection, to offer a find by specification method. 然后,JPA存储库实现可以通过依赖项注入使用我的管理器来提供按规范查找的方法。 Providing a find by specification should drastically reduce the number of methods on our repository interface. 通过规范提供查找应该会大大减少我们存储库接口上的方法数量。

In theory, this all sounds decent, but I feel like I'm missing something critical. 从理论上讲,这听起来不错,但是我觉得我缺少一些关键的东西。 What do you guys think of my proposal, does it comply to the DDD way of thinking? 你们如何看待我的建议,是否符合DDD的思维方式? Or is there already a framework that does something identical to what I just described? 还是已经有一个框架可以执行与我刚刚描述的相同的操作?

Hades is a Repository framework as a wrapper for JPA. Hades是作为JPA的包装器的存储库框架。 It is DDD friendly. 这是DDD友好的。 It supports DDD Specifications out of the box. 它支持开箱用的DDD 规范 I also suggest you look at this article from InfoQ . 我还建议您阅读InfoQ的这篇文章。

I actually read that article, but hades specifications require you to include JPA logic in your specification. 我实际上读过那篇文章,但是hades规范要求您在规范中包括JPA逻辑。 Specifications are domain specific and should be kept separate from any type of persistence logic. 规范是特定于领域的,应与任何类型的持久性逻辑保持分开。

What about JPA annotations man...? 那么JPA批注人...? Do you think your domain objects should be kept seperate from JPA annotations ? 您是否认为您的域对象应该与JPA注释分开?

I think the solution provided by Hades (which is now known as " spring-data-jpa ") is a better solution than the one provided in Evans book : Eric Evans shows an example where a "Specification" calls a "Repository" which itself calls the "Specification" ! 我认为Hades提供的解决方案(现在称为“ spring-data-jpa ”)比Evans书中提供的解决方案更好:Eric Evans展示了一个示例,其中“规范”称为“存储库”称为“规格”! I really wondered how client code would only go through the specification, and not use the repository directly. 我真的很想知道客户端代码将如何仅通过规范,而不直接使用存储库。 The solution provided by Hades/Spring-data-jpa is a good one to me, it's ok to put JPA in domain logic, because JPA is designed to go in the domain layer. Hades / Spring-data-jpa提供的解决方案对我来说是一个很好的解决方案,可以将JPA放在域逻辑中,因为JPA旨在进入域层。

EDIT : I forgot to mention Eric Evans implements a "double dispatch", it's not a silly circular dependecy between specification and repository, but as mentioned above, it doesn't prevent any developper to bypass the specification implementation. 编辑:我忘了提起Eric Evans实现了“双重调度”,这不是规范和存储库之间的愚蠢循环依赖,但是如上所述,它并不能阻止任何开发人员绕过规范实现。

In the .NET world, that is covered by LINQ . 在.NET世界中, LINQ涵盖了这一点。 I know of no Java equivalent. 我知道没有Java等效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM