【问题标题】:How to override Spring Data JPA repository base methods?如何覆盖 Spring Data JPA 存储库基本方法?
【发布时间】:2018-07-27 10:36:42
【问题描述】:

我有一些实体类型需要额外的保存逻辑(准确地说,我想在保存时保存位置)。我不想使用任何特定于数据库的功能,例如触发器,因为我不确定将来使用的数据存储是什么。

所以我想重写save() 方法。

在 Spring Data JPA 文档中,我可以看到为存储库类提供自己的实现的两种方式:

  1. 扩展基础存储库类并告诉 Spring Data 使用它。
  2. 使用实现类 (PositionedRepositoryImpl) 定义接口(在我的情况下,我假设为 PositionedRepository)。

第一种方式的问题 - 我不想为所有存储库实现它,只定位两种实体类型。

第二种方式的问题 - 我无法访问基本存储库方法,因此除了位置计算之外,我还需要以某种方式构建所有查询,这些查询通常由基本存储库提供。

有什么方法可以为特定的存储库类型扩展基础存储库类?

【问题讨论】:

    标签: java spring hibernate spring-data-jpa


    【解决方案1】:

    你可以:

    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
      }
    
    }
    

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

    【讨论】:

      【解决方案2】:

      不要在存储库本身中执行该逻辑。将存储库视为 Java 和数据库之间的哑层。它只是将数据从一端传递到另一端。

      相反,您应该在不同的层处理这种情况。一个更聪明的。业务逻辑层。

      看这个例子:

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

      【讨论】:

      • 很好的答案!但是EntityManager 不是最好的名字,因为它代表了 JPA 中非常具体的东西! PositionedService 保持通用会更清楚:)
      • 我将我的存储库公开为 Spring Data REST 端点,希望将其保留在默认的 Spring 流中。
      • 我将我的存储库公开为 Spring Data REST 端点。它可能有效,但非常不鼓励。我建议在数据库和客户端之间始终至少有 3 层:数据访问层 -> 存储库业务逻辑层 -> 服务通信层-> 控制器。这样你就清楚地划分了责任。 通信处理请求并调用业务逻辑,然后调用数据访问。如果您像这样构建您的应用程序,您将不胜感激
      【解决方案3】:

      作为第三个选项,您可以扩展实现JpaRepositoryJpaSpecificationExecutorSimpleJpaRepository。 通过这种方式,您可以从JpaRepository 的默认实现中受益,同时能够覆盖这些方法。

      例如:

      @Repository
      public class PositionedRepository extends SimpleJpaRepository<Positioned, Long>  {
      
          @Override
          public Positioned save(Positioned positioned) {
                 ...
          }
      
      }
      

      作为第四个选项,您还可以定义自己的 savePositioned() 方法,该方法在后台使用 JpaRepository.save()

      【讨论】:

        猜你喜欢
        • 2018-06-25
        • 2015-03-13
        • 2017-08-20
        • 2016-08-14
        • 2012-10-13
        • 1970-01-01
        • 2012-07-15
        • 2017-01-06
        • 2021-01-28
        相关资源
        最近更新 更多