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.0
和 Spring 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 中的多个基础存储库的主要内容,如果未能解决你的问题,请参考以下文章