【问题标题】:Multiple base repositories in Spring Data JPASpring 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,但不会扩展自定义的。

【问题讨论】:

    标签: java spring-data-jpa


    【解决方案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 注释),并且我有扩展我的基本存储库的单独存储库接口。我发现的一个问题是,在我的数据库中,我所有的实体类数据都在每个实体表中 - 我试图找出这是否与它有关。
    猜你喜欢
    • 2019-08-02
    • 2016-03-12
    • 1970-01-01
    • 2015-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-06
    • 2017-09-07
    相关资源
    最近更新 更多