Spring Data JPA 中的多个基础存储库

Posted

技术标签:

【中文标题】Spring Data JPA 中的多个基础存储库【英文标题】:Multiple base repositories in Spring Data JPA 【发布时间】:2017-03-14 08:41:56 【问题描述】:

我目前正在将一个以 Hibernate ORM 形式自行管理 JPA 的应用程序迁移到 Spring Boot 2.0.0Spring Data JPA 2.0.0。这个应用程序目前有大约 50 个实体,每个实体都有自己的数据源,我现在想将其迁移到 Spring Data Repositories。其中许多数据源具有许多非常相似的功能,即使用自定义过滤器类进行过滤或通过某种不是其 id 的唯一键来获取实体。我可以很好地实现Spring Data JPA Reference 中描述的自定义基类,但这意味着我必须为每个实体提供自定义过滤器,我只需要其中的 10 个。

有没有办法让 Spring Data 合并多个自定义存储库实现,如下所示?


实体:

@Entity
public class Artist 

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    int id;

    @Column(unique = true)
    int secondaryId;
    String name;

    ... constructors, getter, setter, etc ...
    

@Entity
public class Album 

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    int id;

    String name;

    ... constructors, getter, setter, etc ...

具有默认实现的自定义存储库:

public interface FilterRepository<T> 
    public T findByFilter(Filter<T> t);


public class FilterRepositoryImpl<T> implements AdditionalRepository<T> 
    public T findByFilter(Filter<T> t) 
        ... return something ...
    


public interface FindByFieldRepository<T> 
    public T findByField(String fieldName, Object fieldValue);


public class FindByFieldRepositoryImpl<T> implements FindByFieldRepository<T> 
    public T findByField(String fieldName, Object fieldValue) 
        ... return something ...
    

Spring 数据存储库

@Repository
public interface ArtistRepository extends JpaRepository<Artist, Integer>, 
        FilterRepository<Artist>, FindByFieldRepository<Artist> 


@Repository
public interface AlbumRepository extends JpaRepository<Album, Integer>, 
        FilterRepository<Album> 

请注意,ArtistRepository 扩展了两个自定义存储库,而 AlbumRepository 仅扩展了 FilterRepository。另一个存储库可能会扩展 JpaRepository,但不会扩展自定义的。

【问题讨论】:

【参考方案1】:

这应该可以通过两个接口和一个自定义存储库实现来实现。例如:

第一步JpaRepository的简单扩展

@NoRepositoryBean
public interface FilteringJpaRepository<T> extends JpaRepository<T, Long> 
  T findByFilter(Filter<T> t);

第 2 步JpaRepository 的更复杂的扩展

@NoRepositoryBean
public interface ExtendedJpaRepository<T> extends FilteringJpaRepository<T> 
  T findByField(String fieldName, Object fieldValue);

第 3 步:自定义存储库实现

按照问题中链接到的文档中的描述添加自定义存储库实现。还要确保更改 JPA 配置以使用自定义实现。

@NoRepositoryBean
public class ExtendedJpaRepositoryImpl<T>
             extends SimpleJpaRepository<T, Long>
             implements ExtendedJpaRepository<T> 
  ...

  public T findByFilter(Filter<T> t)  ... 

  public T findByField(String fieldName, Object fieldValue)  ... 

第 4 步:根据需要从适当的存储库扩展

public interface AlbumRepository extends FilteringJpaRepository<Album> 

public interface ArtistRepository extends ExtendedJpaRepository<Artist> 

由于功能存储库仅扩展所需的存储库,因此它们的使用者只会看到适合他们的方法。


请参阅sample app 了解此方法。

【讨论】:

虽然这不是我能想到的最漂亮的解决方案,但它肯定是应该工作的。我仍然存在的唯一“问题”是,我不仅有两个自定义存储库,而且还有大约 5 或 6 个(或将来更多)我无法放入任何层次结构中,并且实现所有这些接口的一个类有点丑陋。 嗨,我的存储库设置相同,我有一个扩展 Spring 的 CrudRepository 的基本存储库(使用 @NoRepositoryBean 注释),并且我有扩展我的基本存储库的单独存储库接口。我发现的一个问题是,在我的数据库中,我所有的实体类数据都在每个实体表中 - 我试图找出这是否与它有关。

以上是关于Spring Data JPA 中的多个基础存储库的主要内容,如果未能解决你的问题,请参考以下文章

在 JPA 存储库(Spring Data Jpa)中执行自定义查询

延迟加载 Spring Data JPA 存储库

Spring Data Rest 中同一实体的多个存储库

Spring Data Jpa / Hades 事务行为

spring data jpa中的存储是啥?

Spring -data-jpa ,存储库类不起作用