我希望了解Generic Repository模式。我有一个通用服务接口,它由抽象服务实现,由所有服务实现扩展。我想确保所有CRUD操作和按标准/规范搜索都在抽象服务中进行。
我的所有存储库都是扩展JpaRepository和JpaSpecificationExecutor的接口。但是,我无法在抽象服务中使用自动装配的存储库执行findAll(规范,可分页)。
我应该对结构做出哪些更改,以便我可以利用JpaSpecificationExecutor的方法?
服务接口:
public interface GenericFoo<T, S> {
public List<T> search(S criteria, Pageable pageable) {
}
摘要服务:
public abstract class Foo<T, S> implements GenericFoo<T, S> {
@Autowired
private JpaRepository<T, Long> repository;
public List<T> search(S criteria, Pageable pageable) {
//throws compilation error
repository.findAll(getSpecification(criteria), pageable);
}
protected abstract Specification<T> getSpecification(S criteria);
}
ServiceImpl:
@Component
@Transactional
public class BarServiceImpl extends Foo<Bar, BarSearchCriteria> implements GenericFoo {
protected Specification<Bar> getSpecification(BarSearchCriteria criteria) {
//implementation to be filled for each service
return null;
}
}
存储库:
public interface BarRepository extends JpaRepository<Bar, Long>, JpaSpecificationExecutor<Bar> {
}
修改 我也尝试了以下操作,虽然编译错误消失了,但由于自动装配异常,应用程序仍然无法启动。
SimpleJpaRepository:
public interface SimpleRepository<T> extends JpaRepository<T, Long>, JpaSpecificationExecutor<T> {
}
BaseService:
public abstract class BaseService<T, S> implements GenericService<T, S> {
@Autowired
private SimpleJpaRepository<T, Long> simpleJpaRepository;
public List<T> search(S criteria, Pageable pageable) {
repository.findAll(getSpecification(criteria), pageable);
}
protected abstract Specification<T> getSpecification(S criteria);
}
存储库:
public interface BarRepository extends SimpleJpaRepository<Bar, Long> {
}
堆栈跟踪:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.data.jpa.repository.support.SimpleJpaRepository com.foopackage.barpackage.services.BaseService.simpleJpaRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.data.jpa.repository.support.SimpleJpaRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573) ~[spring-beans-4.2.8.RELEASE.jar:4.2.8.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.2.8.RELEASE.jar:4.2.8.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331) ~[spring-beans-4.2.8.RELEASE.jar:4.2.8.RELEASE]
... 22 common frames omitted
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.data.jpa.repository.support.SimpleJpaRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1380) ~[spring-beans-4.2.8.RELEASE.jar:4.2.8.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1126) ~[spring-beans-4.2.8.RELEASE.jar:4.2.8.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1021) ~[spring-beans-4.2.8.RELEASE.jar:4.2.8.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545) ~[spring-beans-4.2.8.RELEASE.jar:4.2.8.RELEASE]
... 24 common frames omitted
答案 0 :(得分:0)
我应该对结构做出哪些更改,以便我可以利用JpaSpecificationExecutor的方法?
创建和使用这样的中间界面应该可以解决问题:
public interface RepositoryWithExecutor<T> extends JpaRepository<T, Long>, JpaSpecificationExecutor<Bar> {}
现在您的BarRepository只是扩展RepositoryWithExecutor<Bar>
Foo<T>
的存储库也应该是RepositoryWithExecutor<T>
已更新以回答更改后的问题
您正尝试自动装配SimpleJpaRepository<T, Long>
类型的字段,但您ApplicationContext
知道的所有字段都是BarRepository
SimpleJpaRepository<Bar, Long>
您需要SimpleJpaRepository<T, Long>
的通用实现,或者您必须创建BaseService
的专用版本,T
专门针对Bar
并引用该专用版本。< / p>
旁注:我不认为你实际上正在显示你正在使用的代码,因为BaseService
是抽象的,Spring不应该尝试实例化它。
答案 1 :(得分:0)
尝试这个:
@Autowired
private SimpleJpaRepository<T> simpleJpaRepository;
只需删除SimpeJpaRepository接口中的Long参数即可。