【问题标题】:Accessing JPA-methods via inheritance and type parameterized repository通过继承和类型参数化存储库访问 JPA 方法
【发布时间】:2020-03-05 17:16:16
【问题描述】:

假设我有一个抽象实体

@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())));
}

我只想有一个方法调用,如下面的伪代码(我知道不能实例化抽象类),它将实体作为参数的抽象实体,调用孩子的 repo 并在该特定孩子中执行 jpa 方法回购。

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&lt;C&gt; findByName(String name); 添加到 SuperRepository 然后创建一个实现实体存储库特定事务方法的新服务。在实现 AbstractEntity 与实体特定方法之间的映射时,在上一个服务中调用此服务:

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

【问题讨论】:

  • eeee 为什么不使用findById ??.....
  • 我没有 id,我通过 Example.Matcher 搜索名称
  • 这个名字是不是到处都是name
  • 是的,到处都是这样命名的
  • findByName 然后。

标签: java inheritance spring-data-jpa


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2014-09-13
    • 1970-01-01
    • 1970-01-01
    • 2021-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-07
    • 2012-08-16
    相关资源
    最近更新 更多