java - 通过继承和类型参数化存储库访问 JPA 方法

标签 java inheritance spring-data-jpa

假设我有一个抽象实体

@MappedSuperclass
@Data
public abstract class AbstractEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(nullable = false, updatable = false)
    protected Integer id;
    @Column(nullable = false, unique = true)
    protected String name;

}

使用某种 AbstractRepository

@NoRepositoryBean
public interface AbstractRepository<C extends AbstractEntity> extends JpaRepository<C, Integer> {}

这应该充当多个实体的单个依赖项。实体扩展了抽象实体,从而扩展了 AbstractRepository:

public interface RealEntityRepository extends AbstractRepository<RealEntity> {}

在我的服务中,我想使用 jpa 继承来摆脱臃肿的构造函数(由于 realEntityRepos 太多而变得臃肿)和每个实体的方法实现。因此,而不是每个实体都有 x 个这样的方法

void findRealEntity(RealEntity entity) {
    entity.setId(realEntityRepository.findOne(entity.getName())
            .map(RealEntity ::getId)
            .orElseThrow(() -> new SomeException(entity.getName())));
}

我只想有一个方法调用,如下面的伪代码(我知道无法实例化抽象类),该方法将实体作为参数的抽象实体,调用子项的存储库并执行该特定子项中的 jpa 方法 repo 。

void findEntity(AbstractEntity entity) {
entity.setId(abstractEntityRepository.findOne(entity.getName())
        .map(AbstractEntity::getId)
        .orElseThrow(() -> new SomeException(entity.getName())));

}

这是我现在的服务,它确实可以像那样工作,但它很臃肿:

@Service
public class SomeService {

private final RealEntity1Repository realEntity1Repository;
private final RealEntity2Repository realEntity2Repository;
private final RealEntity3Repository realEntity3Repository ;
... 5 more times ..

public SomeService(RealEntity1Repository realEntity1Repository, RealEntity2Repository realEntity2Repository,
                            RealEntity3Repository realEntity3Repository,
 ... 5 more) {
    this.realEntity1Repository = realEntity1Repository;
    this.realEntity2Repository = realEntity2Repository;
    this.realEntity3Repository = realEntity3Repository;
    ... 5 more
}
... some methods

void findRealEntity1(RealEntity1 entity) {
entity.setId(realEntity1Repository.findOne(entity.getName())
        .map(RealEntity1::getId)
        .orElseThrow(() -> new SomeException(entity.getName())));
}

void findRealEntity2(RealEntity2 entity) {
entity.setId(realEntity2Repository.findOne(entity.getName())
        .map(RealEntity2::getId)
        .orElseThrow(() -> new SomeException(entity.getName())));
}
...

更新

感谢 @Antoniosss 的提示,我解决了问题!

添加Optional<C> findByName(String name);到 super 存储库 然后创建一个新服务来实现实体存储库特定的事务方法。在实现AbstractEntity和实体特定方法之间的映射时,在之前的服务中调用此服务:

public void mapAbstractEntity(AbstractEntity abstractEntity) {
  if (abstractEntity instanceof RealEntity1 { // call RealEntity1 method from service}
  else if (abstractEntity instanceof RealEntity2) { ... }

最佳答案

基于实际代码 - 您可以将 findByName 通用方法添加到抽象存储库,创建将实体类型映射到存储库的映射,然后使用 findRealEntity(AbstractEntity) 的单一实现这将选择正确的存储库并对其调用 findByName

关于java - 通过继承和类型参数化存储库访问 JPA 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60550782/

相关文章:

java - 在 Java 中,如何从组件类型的类中获取类的数组?

python - 覆盖python中的属性

java - 使用 Spring AOP 触发了哪个接口(interface)(扩展 CrudRepository)的删除方法?

java - 由 : java. lang.UnsupportedOperationException: null Lombok with List 引起

java - Spring Data 2.0.x AuditorAware getCurrentUser 方法抛出 AbstractMethodError

java - 在 Eclipse Java 项目之间添加引用

java - 从 6.3 升级时的 Hybris 6.7 服务器启动问题

c++ - 使用基类指针调用函数?

c++ - 在C++中使用全局变量初始化

java - 使 Java 类通用,但仅适用于两种或三种类型