简体   繁体   English

如何重写Spring Data JPA存储库的基本方法?

[英]How to override Spring Data JPA repository base methods?

I have some entity type that needs additional logic on saving (to be precise, I want to save position at the moment of saving). 我有一些实体类型,在保存时需要其他逻辑(确切地说,我想在保存时保存位置)。 I don't want to do it with any DB-specific features, like triggers, because I'm not sure what will be the data storage used in future. 我不想使用任何特定于数据库的功能(例如触发器)来完成此操作,因为我不确定将来将使用什么数据存储。

So I would like to override save() method. 所以我想重写save()方法。

In Spring Data JPA documentation I can see two ways of providing own implementation for repository classes: 在Spring Data JPA文档中,我可以看到两种为仓库类提供自己的实现的方法:

  1. Extend base repository class and tell Spring Data to use it. 扩展基础存储库类,并告诉Spring Data使用它。
  2. Defining an interface (in my case I assume PositionedRepository ) with an implementation class ( PositionedRepositoryImpl ). 定义一个接口(在我的情况下,我认为PositionedRepository )有一个实现类( PositionedRepositoryImpl )。

Problem with first way - I don't want to implement it for all repositories, only two entity types are positioned. 第一种方法的问题-我不想为所有存储库实现它,只定位了两种实体类型。

Problem with second way - I don't have access to base repository methods, so apart from position calculation I would need to somehow build all of the queries, normally provided by base repository. 第二种方法的问题-我无权访问基础存储库方法,因此除了位置计算之外,我还需要以某种方式构建通常由基础存储库提供的所有查询。

Any way to extend base repository class just for specific repository types? 有什么方法可以仅针对特定存储库类型扩展基本存储库类?

Don't do that logic in the repository itself. 不要在存储库本身中执行该逻辑。 Think about repositories as a dumb layer between java and the database. 将存储库视为Java和数据库之间的愚蠢层。 It just passes data from end to the other. 它只是将数据从一端传递到另一端。

Instead you should handle that case in a different layer. 相反,您应该在另一层处理这种情况。 A more intelligent one. 更聪明的一个。 The business logic layer. 业务逻辑层。

See this example: 请参阅以下示例:

@Service
public class MyEntityService{

     private final MyEntityRepository myEntityRepository;
     private final OtherEntityRepository otherEntityRepository;

     @Autowired
     public MyEntityService(MyEntityRepository myEntityRepository, 
                          OtherEntityRepository otherEntityRepository){
         this.myEntityRepository = myEntityRepository;
         this.otherEntityRepository = otherEntityRepository;
     }

     public void save(MyEntity myEntity){
          // do stuff with otherEntityRepository
          myEntitiyRepository.save(myEntity);
     }
}

As third option you can extend SimpleJpaRepository that implements JpaRepository and JpaSpecificationExecutor . 作为第三个选择,你可以扩展SimpleJpaRepository实现JpaRepositoryJpaSpecificationExecutor In this way, you could benefit from the default implementation of JpaRepository while being the ability to override these methods. 这样,您可以从JpaRepository的默认实现中JpaRepository同时可以覆盖这些方法。

For example : 例如 :

@Repository
public class PositionedRepository extends SimpleJpaRepository<Positioned, Long>  {

    @Override
    public Positioned save(Positioned positioned) {
           ...
    }

}

As fourth option you can also define your own savePositioned() method that uses under the hood the JpaRepository.save() . 作为第四个选项,您还可以定义自己的savePositioned()方法,该方法在JpaRepository.save()JpaRepository.save()使用。

you can : 您可以 :

public class CustomJpaRepository<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> {
  private final JpaEntityInformation<T, ?> entityInformationWrap;
  private final EntityManager emWrap;
  public CustomJpaRepository(JpaEntityInformation entityInformation, EntityManager entityManager) {
    super(entityInformation, entityManager);
    entityInformationWrap=entityInformation;
    emWrap=entityManager;
  }

  @Override
  public <S extends T> S save(S entity) {
    //doing
  }

}

then main class add: @EnableJpaRepositories(repositoryBaseClass = CustomJpaRepository.class) 然后主类添加:@EnableJpaRepositories(repositoryBaseClass = CustomJpaRepository.class)

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

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