了解弹簧数据 JPA @NoRepositoryBean界面

2022-08-31 12:20:15

我在阅读Spring Data文档时多次遇到该界面。@NoRepositoryBean

引用文档:

如果您使用Spring命名空间的自动存储库接口检测,则使用该接口,就像这样将导致Spring尝试创建MyRepository的实例。这当然不是必需的,因为它只是在存储库和要为每个实体定义的实际存储库接口之间充当中介。要排除扩展存储库的接口,请将其实例化为存储库实例,请使用 对其进行注释。@NoRepositoryBean

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


答案 1

该注释用于避免为实际与存储库接口的条件匹配但并非旨在成为存储库接口的接口创建存储库代理。只有在您开始使用功能扩展所有存储库时才需要它。让我举个例子:

假设你想向所有存储库添加一个 foo() 方法。首先添加类似如下的存储库接口

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" />

你使用,因为你在同一个包中。Spring Data 基础架构现在无法判断 它不是一个具体的存储库接口,而是充当中间存储库来公开其他方法。因此,它将尝试为其创建存储库代理实例并失败。现在,您可以使用来注释此中间接口,以基本上告诉Spring Data:不要为此接口创建存储库代理bean。com.foobarCustomerRepositoryMyBaseRepository@NoRepositoryBean

这种情况也是原因,并且也带有此注释。如果软件包扫描意外地选择了它们(因为您不小心以这种方式配置了它),则引导程序将失败。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行为是为存储库的所有子接口创建一个实现。

public interface ExtendedStudentRepository extends ExtendedRepository<Student, Long> {
}

推荐