ChatGPT解决这个技术问题 Extra ChatGPT

了解 Spring Data JPA @NoRepositoryBean 接口

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

从文档中引用:

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

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


O
Oliver Drotbohm

注释用于避免为实际匹配 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 实例。


m
m.nguyencntt

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

@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> {
}