繁体   English   中英

Spring Data:抽象基础服务中的JPA存储库,用于调用带有规范的findAll

[英]Spring Data: JPA Repository in abstract base service to call findAll with specification

我希望了解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

我应该对结构做出哪些更改,以便我可以利用JpaSpecificationExecutor的方法?

创建和使用这样的中间接口应该可以解决问题:

public interface RepositoryWithExecutor<T> extends JpaRepository<T, Long>, JpaSpecificationExecutor<Bar> {}

现在,您的BarRepository只是扩展了RepositoryWithExecutor<Bar>

Foo<T>RepositoryWithExecutor<T>也应该是RepositoryWithExecutor<T>

更新以回答更改的问题

您正在尝试自动SimpleJpaRepository<T, Long>类型的字段,但您的所有ApplicationContext知道BarRepositorySimpleJpaRepository<Bar, Long>

您需要SimpleJpaRepository<T, Long>的通用实现,或者您必须创建具有T专用于Bar专用版本的BaseService并引用该专用版本。

旁注:我认为你实际上并没有显示你正在使用的代码,因为BaseService是抽象的,Spring不应该尝试实例化它。

试试这个:

 @Autowired
 private SimpleJpaRepository<T> simpleJpaRepository;

只需删除SimpeJpaRepository接口中的Long参数即可。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM