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
。但这在很多情况下可能没有意义。
我正在使用 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
。但这在很多情况下可能没有意义。