Spring JPA 自定义存储库实现不起作用

Spring JPA custom repository implementation does not work

我正在使用 Spring Data JPA 1.10。11.RELEASE

我有一个我所有其他存储库都扩展的基本存储库。这部分有效。

@NoRepositoryBean
public interface BaseRepository<T, ID> extends JpaRepository<T, Long> {
    T findById(ID id);
    List<T> getByIds(Collection<ID> ids);
    Map<ID, T> getMapByIds(Collection<ID> ids);
}

public class BaseRepositoryImpl<T, ID> extends
    SimpleJpaRepository<T, Long> implements BaseRepository<T, ID> {
    
    // implementations
}

我还想为 一些 的存储库声明自定义接口以进行扩展。所以我声明了一个接口和一个“Impl”class:

public interface TestRepository<T> {
    int myTestMethod(OffsetDateTime threshold);
}

@Repository
public class TestRepositoryImpl<T> implements TestRepository<T> {

    @Override
    public int myTestMethod(OffsetDateTime threshold) {
        System.out.println("myTestMethod");
        return 100;
    }
}

然后,我创建一个现有的工作存储库来扩展这个新接口:

@Repository
public interface MyEntityDataRepository extends
    BaseRepository<MyEntity, MyEntityId>,
    TestRepository<MyEntity> {

    MyEntity findBySomeCriteria(....);
}

注意:此存储库在之前扩展 TestRepository 时有效,但按上述方式扩展后,应用程序上下文将无法启动并出现错误:

Caused by: org.springframework.data.mapping.PropertyReferenceException: No property myTestMethod found for type MyEntity!
    at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:77)
    at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:329)
    at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:309)
    at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:272)
    at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:243)
    at org.springframework.data.repository.query.parser.Part.<init>(Part.java:76)
......

配置如下:

<jpa:repositories
  base-package="com.xxx.repository"
  base-class="com.xxx.repository.BaseRepositoryImpl"
  transaction-manager-ref="transactionManager"
  entity-manager-factory-ref="entityManagerFactory"
/>

我觉得我一直在严格遵循 Spring 数据文档中的示例。我还尝试使用接口和实现名称,并添加了

repository-impl-postfix="Impl"

到配置。一切都是徒劳的。我每次都得到同样的错误。

有没有人看到这个问题并解决了?非常感谢您的帮助。

我将在调查后回答我自己的问题。

在 Spring 的文档 here 中,CustomRepository/Impl 机制只能用于 单个 存储库。如果你想创建一些由多个存储库继承的自定义实现,你必须自定义 base 存储库,它将用于支持 all 存储库 bean。

所以我最终添加了一个 int myTestMethod(OffsetDateTime threshold) 实现到基本存储库 impl BaseRepositoryImpl。此方法将用于支持 MyEntityDataRepository 中声明的扩展 TestRepository 的方法。注意:您必须让您的存储库扩展声明自定义方法的接口。否则,基本存储库 impl 中的函数将不适用于仅作为接口代理的存储库 bean,而不是基本存储库 impl。

此外,如果您在实体存储库中自定义相同的方法,您实际上可以覆盖基本存储库的实现。

这并不理想,但它确实有效。我希望我可以将自定义方法的可用性限制为仅 一些 存储库。一种方法是将不同的存储库“组”分成单独的不相交的包,并为每个单独的搜索路径声明一个不同的 base-class。但这在很多情况下可能没有意义。