了解 Spring Data JPA @NoRepositoryBean 接口

Posted

技术标签:

【中文标题】了解 Spring Data JPA @NoRepositoryBean 接口【英文标题】:Understanding the Spring Data JPA @NoRepositoryBean interface 【发布时间】:2012-07-19 13:57:26 【问题描述】:

我在阅读 Spring Data 文档时多次遇到@NoRepositoryBean 接口。

引用文档:

如果您使用自动存储库接口检测,则使用 使用接口的 Spring 命名空间原样会导致 Spring 试图创建 MyRepository 的实例。这当然不是 需要,因为它只是充当存储库和 您要为每个实体定义的实际存储库接口。到 排除扩展存储库的接口被实例化为 存储库实例用 @NoRepositoryBean 注释它。

但是,我仍然不确定何时何地使用它。有人可以建议并给我一个具体的用法示例吗?

【问题讨论】:

【参考方案1】:

注解用于避免为实际上符合 repo 接口标准但不打算成为一个标准的接口创建存储库代理。仅当您开始使用功能扩展所有存储库时才需要它。举个例子吧:

假设您想将方法 foo() 添加到所有存储库。您可以从添加这样的 repo 接口开始

public interface com.foobar.MyBaseInterface<…,…> extends CrudRepository<…,…> 

  void foo();

您还可以添加相应的实现类、工厂等。您的具体存储库接口现在将扩展该中间接口:

public interface com.foobar.CustomerRepository extends MyBaseInterface<Customer, Long> 


现在假设您引导 - 比如说 Spring Data JPA - 如下:

<jpa:repositories base-package="com.foobar" />

您使用com.foobar 是因为您在同一个包中拥有CustomerRepository。 Spring Data 基础设施现在无法判断 MyBaseRepository 不是具体的存储库接口,而是充当中间存储库以公开附加方法。所以它会尝试为它创建一个存储库代理实例并失败。您现在可以使用@NoRepositoryBean 来注释这个中间接口,本质上告诉 Spring Data:不要为这个接口创建存储库代理 bean。

这种情况也是CrudRepositoryPagingAndSortingRepository也带有这个注解的原因。如果包扫描偶然发现了这些(因为您不小心以这种方式配置了它),则引导程序将失败。

长话短说:使用注释来防止存储库接口被选为候选最终成为存储库 bean 实例。

【讨论】:

【参考方案2】:

我们可以声明一个新接口作为我们的自定义方法:

@NoRepositoryBean
public interface ExtendedRepository<T, ID extends Serializable> extends JpaRepository<T, ID> 
    List<T> findByAttributeContainsText(String attributeName, String text);

我们的接口扩展了 JpaRepository 接口,因此我们将从所有标准行为中受益。

您还会注意到我们添加了@NoRepositoryBean 注释。这是必要的,否则,默认的 Spring 行为是为 Repository 的所有子接口创建一个实现。

public interface ExtendedStudentRepository extends ExtendedRepository<Student, Long> 

【讨论】:

以上是关于了解 Spring Data JPA @NoRepositoryBean 接口的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 Spring Data JPA 了解底层数据库名称

spring data jpa详解

Spring Data 系列学习Spring Data JPA 基础查询

了解 Spring Data 接口

纯干货,Spring-data-jpa详解(转)

Spring-data-jpa详解,全方位介绍。