简体   繁体   English

多个实体的通用 JPA 存储库

[英]Generic JPA repository for multiple entities

I have several entities and use Spring Data JPA repositories with specifications query my database.我有几个实体,并使用Spring Data JPA存储库和规范查询我的数据库。 Therefore I created a generic class SpecBuilder to build my queries based on a query description ( MyQueryDescriptor ).因此,我创建了一个通用类SpecBuilder来基于查询描述 ( MyQueryDescriptor ) 构建我的查询。

public class Specs {
  public static <T extends MyEntityIFace> Specification<T> myfind(final MyQueryDescriptor qDesc) {
    return new Specification<T>() {
      @Override
      public Predicate toPredicate(Root<T> root, 
               CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
        try {
          return SpecBuilder.mySpec(root, criteriaQuery, criteriaBuilder, qDesc);
        } catch (Exception e) {
          ...handle error...
        }
      }
    };
  }
}

My repositories:我的存储库:

public interface Entity1DAO extends Repository<Entity1,Long>, 
                                    JpaSpecificationExecutor {
}

and

public interface Entity2DAO extends Repository<Entity2,Long>, 
                                    JpaSpecificationExecutor {
}

Now there are 3 things I am not quite sure about:现在有三件事我不太确定:
1) 1)
Is this use of a generic SpecBuilder a clean design?这种通用 SpecBuilder 的使用是一种简洁的设计吗?

2) 2)
Is there a way to avoid writing those repository interfaces for each entity?有没有办法避免为每个实体编写这些存储库接口? Let's say a generic repository?让我们说一个通用的存储库?

3) 3)
The MyQueryDescriptor class has a method to return an instance of an Entity, which will be queried. MyQueryDescriptor类有一个方法来返回一个 Entity 的实例,该实例将被查询。
What would be a clean way to obtain the according repository based on the entity class, avoiding a switch case?什么是基于实体类获取相应存储库的干净方法,避免切换案例? I was thinking about putting an annotation with the specific repository class to each entity but it feels a bit smelly.我正在考虑为每个实体添加一个带有特定存储库类的注释,但感觉有点臭。
Should I create a factory and inject a map like我应该创建一个工厂并注入一个像

Entity1.class => Entity1DAO
Entity2.class => Entity2DAO

? ?

You can use entity inheritance and use Spring Expression Language (SpEL) to make repository issue calls on right entities.您可以使用实体继承并使用Spring 表达式语言(SpEL) 对正确的实体进行存储库问题调用。 Like in my last update here在我的最后一次更新喜欢这里

Is this use of a generic SpecBuilder a clean design?这种通用 SpecBuilder 的使用是一种简洁的设计吗?

Depends what criteria you have for clean design.取决于您对简洁设计的标准。 Will the same MyQueryDescriptor work for different entities?相同的MyQueryDescriptor适用于不同的实体? Surely they have different properties, so you need to ask yourself whether a given MyQueryDescriptor could be mistakenly used for an incompatible entity and ways in which you could prevent it.当然,它们具有不同的属性,因此您需要问自己给定的MyQueryDescriptor是否会被错误地用于不兼容的实体以及如何防止它。 We cannot comment on that since we don't know how your SpecBuilder works.我们无法对此发表评论,因为我们不知道您的SpecBuilder是如何工作的。

Is there a way to avoid writing those repository interfaces for each entity?有没有办法避免为每个实体编写这些存储库接口? Let's say a > generic repository?假设一个 > 通用存储库?

Nope.不。 It's not much boilerplate either, though.不过,它也不是很多样板。

  1. The MyQueryDescriptor class has a method to return an instance of an Entity, which will be queried. MyQueryDescriptor 类有一个方法来返回一个 Entity 的实例,该实例将被查询。 What would be a clean way to obtain the according repository based on the entity class, avoiding a switch case?什么是基于实体类获取相应存储库的干净方法,避免切换案例?

I suppose you could use getBeanProvider at runtime, where you would define resolvableType as CrudRepository<MyEntityType, IdType> .我想你可以使用getBeanProvider在运行时,在这里你将定义resolvableTypeCrudRepository<MyEntityType, IdType>

However, if I were you, I'd consider switching to using JPA Criteria API without the JpaSpecificationExecutor abstraction on top of it.但是,如果我是您,我会考虑切换到使用 JPA Criteria API,而在它之上没有JpaSpecificationExecutor抽象。 That would probably prove to be more natural.那可能会被证明是更自然的。 The design of Spring repositories is centered around the idea of the repository organizing queries around the given specific entity, whereas your use case seems to go in exactly the opposite direction - to dynamically pick an entity and then find a repository to fit in, just to satisfy Spring's restrictions. Spring 存储库的设计以存储库围绕给定的特定实体组织查询的想法为中心,而您的用例似乎正好相反 - 动态选择一个实体,然后找到一个适合的存储库,只是为了满足 Spring 的限制。 You seem to be fighting the framework in that regard.您似乎在这方面与框架作斗争。

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

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