Jpa 有没有办法通过QueryDSL中的谓词API获取惰性关系?

Jpa 有没有办法通过QueryDSL中的谓词API获取惰性关系?,jpa,spring-data,querydsl,Jpa,Spring Data,Querydsl,我正在使用SpringDataJPA项目中的QueryDSLDPredicateExecutor,我面临着获取惰性关系的需要。我知道我可以在Repository接口中使用本机JPA-QL查询,甚至可以使用QueryDSL中的JPAQLQuery,但我很好奇这是否可能,以便为将来的需要构建查询。我遇到了类似的问题,在使用谓词和QueryDSLPirector时,我必须获取联接集合 我所做的是创建一个自定义存储库实现,添加一个方法,允许我定义应该获取的实体 不要被这里的大量代码吓倒,它实际上非常简单

我正在使用SpringDataJPA项目中的
QueryDSLDPredicateExecutor
,我面临着获取惰性关系的需要。我知道我可以在Repository接口中使用本机JPA-QL查询,甚至可以使用QueryDSL中的JPAQLQuery,但我很好奇这是否可能,以便为将来的需要构建查询。

我遇到了类似的问题,在使用谓词和QueryDSLPirector时,我必须获取联接集合

我所做的是创建一个自定义存储库实现,添加一个方法,允许我定义应该获取的实体

不要被这里的大量代码吓倒,它实际上非常简单,您只需要做很少的更改就可以在应用程序中使用它

这是自定义存储库的界面

@NoRepositoryBean
public interface JoinFetchCapableRepository<T, ID extends Serializable> extends     JpaRepository<T, ID>, QueryDslPredicateExecutor<T> {

    Page<T> findAll(Predicate predicate, Pageable pageable, JoinDescriptor... joinDescriptors);
}
public class JoinFetchCapableRepositoryImpl <T, ID extends Serializable> extends QueryDslJpaRepository<T, ID> implements JoinFetchCapableRepository<T, ID> {

    private static final EntityPathResolver DEFAULT_ENTITY_PATH_RESOLVER = SimpleEntityPathResolver.INSTANCE;

    private final EntityPath<T> path;
    private final PathBuilder<T> builder;
    private final Querydsl querydsl;

    public JoinFetchCapableRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager) {
        this(entityInformation, entityManager, DEFAULT_ENTITY_PATH_RESOLVER);
    }

    public JoinFetchCapableRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager, EntityPathResolver resolver) {
        super(entityInformation, entityManager, resolver);
        this.path = resolver.createPath(entityInformation.getJavaType());
        this.builder = new PathBuilder<>(path.getType(), path.getMetadata());
        this.querydsl = new Querydsl(entityManager, builder);
    }

    @Override
    public Page<T> findAll(Predicate predicate, Pageable pageable, JoinDescriptor... joinDescriptors) {
        JPQLQuery countQuery = createQuery(predicate);
        JPQLQuery query = querydsl.applyPagination(pageable, createFetchQuery(predicate, joinDescriptors));

        Long total = countQuery.count();
        List<T> content = total > pageable.getOffset() ? query.list(path) : Collections.<T> emptyList();

        return new PageImpl<>(content, pageable, total);
    }

    protected JPQLQuery createFetchQuery(Predicate predicate, JoinDescriptor... joinDescriptors) {
        JPQLQuery query = querydsl.createQuery(path);
        for(JoinDescriptor joinDescriptor: joinDescriptors)
            join(joinDescriptor, query);
        return query.where(predicate);
    }

    private JPQLQuery join(JoinDescriptor joinDescriptor, JPQLQuery query) {
        switch(joinDescriptor.type) {
            case DEFAULT:
                throw new IllegalArgumentException("cross join not supported");
            case INNERJOIN:
                query.innerJoin(joinDescriptor.path);
                break;
            case JOIN:
                query.join(joinDescriptor.path);
                break;
            case LEFTJOIN:
                query.leftJoin(joinDescriptor.path);
                break;
            case RIGHTJOIN:
                query.rightJoin(joinDescriptor.path);
                break;
            case FULLJOIN:
                query.fullJoin(joinDescriptor.path);
                break;
        }
        return query.fetch();
    }
}
public class JoinFetchCapableQueryDslJpaRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable>
        extends JpaRepositoryFactoryBean<R, T, I> {

    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {

        return new JoinFetchCapableQueryDslJpaRepositoryFactory(entityManager);
    }
    private static class JoinFetchCapableQueryDslJpaRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory {

        private EntityManager entityManager;

        public JoinFetchCapableQueryDslJpaRepositoryFactory(EntityManager entityManager) {
            super(entityManager);
            this.entityManager = entityManager;
        }

        protected Object getTargetRepository(RepositoryMetadata metadata) {
            return new JoinFetchCapableRepositoryImpl<>(getEntityInformation(metadata.getDomainType()), entityManager);
        }

        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
            return JoinFetchCapableRepository.class;
        }
    }
}
自定义存储库的实现

@NoRepositoryBean
public interface JoinFetchCapableRepository<T, ID extends Serializable> extends     JpaRepository<T, ID>, QueryDslPredicateExecutor<T> {

    Page<T> findAll(Predicate predicate, Pageable pageable, JoinDescriptor... joinDescriptors);
}
public class JoinFetchCapableRepositoryImpl <T, ID extends Serializable> extends QueryDslJpaRepository<T, ID> implements JoinFetchCapableRepository<T, ID> {

    private static final EntityPathResolver DEFAULT_ENTITY_PATH_RESOLVER = SimpleEntityPathResolver.INSTANCE;

    private final EntityPath<T> path;
    private final PathBuilder<T> builder;
    private final Querydsl querydsl;

    public JoinFetchCapableRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager) {
        this(entityInformation, entityManager, DEFAULT_ENTITY_PATH_RESOLVER);
    }

    public JoinFetchCapableRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager, EntityPathResolver resolver) {
        super(entityInformation, entityManager, resolver);
        this.path = resolver.createPath(entityInformation.getJavaType());
        this.builder = new PathBuilder<>(path.getType(), path.getMetadata());
        this.querydsl = new Querydsl(entityManager, builder);
    }

    @Override
    public Page<T> findAll(Predicate predicate, Pageable pageable, JoinDescriptor... joinDescriptors) {
        JPQLQuery countQuery = createQuery(predicate);
        JPQLQuery query = querydsl.applyPagination(pageable, createFetchQuery(predicate, joinDescriptors));

        Long total = countQuery.count();
        List<T> content = total > pageable.getOffset() ? query.list(path) : Collections.<T> emptyList();

        return new PageImpl<>(content, pageable, total);
    }

    protected JPQLQuery createFetchQuery(Predicate predicate, JoinDescriptor... joinDescriptors) {
        JPQLQuery query = querydsl.createQuery(path);
        for(JoinDescriptor joinDescriptor: joinDescriptors)
            join(joinDescriptor, query);
        return query.where(predicate);
    }

    private JPQLQuery join(JoinDescriptor joinDescriptor, JPQLQuery query) {
        switch(joinDescriptor.type) {
            case DEFAULT:
                throw new IllegalArgumentException("cross join not supported");
            case INNERJOIN:
                query.innerJoin(joinDescriptor.path);
                break;
            case JOIN:
                query.join(joinDescriptor.path);
                break;
            case LEFTJOIN:
                query.leftJoin(joinDescriptor.path);
                break;
            case RIGHTJOIN:
                query.rightJoin(joinDescriptor.path);
                break;
            case FULLJOIN:
                query.fullJoin(joinDescriptor.path);
                break;
        }
        return query.fetch();
    }
}
public class JoinFetchCapableQueryDslJpaRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable>
        extends JpaRepositoryFactoryBean<R, T, I> {

    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {

        return new JoinFetchCapableQueryDslJpaRepositoryFactory(entityManager);
    }
    private static class JoinFetchCapableQueryDslJpaRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory {

        private EntityManager entityManager;

        public JoinFetchCapableQueryDslJpaRepositoryFactory(EntityManager entityManager) {
            super(entityManager);
            this.entityManager = entityManager;
        }

        protected Object getTargetRepository(RepositoryMetadata metadata) {
            return new JoinFetchCapableRepositoryImpl<>(getEntityInformation(metadata.getDomainType()), entityManager);
        }

        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
            return JoinFetchCapableRepository.class;
        }
    }
}
public类JoinFetchCapableRepositoryImpl扩展QueryDslJpaRepository实现JoinFetchCapableRepository{
私有静态最终EntityPathResolver默认\u实体\u路径\u解析器=SimpleEntityPathResolver.INSTANCE;
私有最终实体路径;
私有最终路径生成器;
私人最终查询码查询码查询码查询码;
public JoinFetchCapableRepositoryImpl(JpaEntityInformation entityInformation,EntityManager EntityManager){
这(entityInformation、entityManager、默认实体路径解析器);
}
public JoinFetchCapableRepositoryImpl(JpaEntityInformation entityInformation,EntityManager EntityManager,EntityPathResolver resolver){
超级(实体信息、实体管理器、解析器);
this.path=resolver.createPath(entityInformation.getJavaType());
this.builder=新的PathBuilder(path.getType(),path.getMetadata());
this.querydsl=新的querydsl(entityManager,builder);
}
@凌驾
公共页findAll(谓词谓词、可分页、JoinDescriptor…JoinDescriptor){
JPQLQuery countQuery=createQuery(谓词);
JPQLQuery query=querydsl.applyPagination(可分页,createFetchQuery(谓词,joinDescriptors));
Long total=countQuery.count();
List content=total>pageable.getOffset()?query.List(路径):Collections.emptyList();
返回新的PageImpl(内容、可分页、总计);
}
受保护的JPQLQuery createFetchQuery(谓词谓词、JoinDescriptor…JoinDescriptor){
JPQLQuery query=querydsl.createQuery(路径);
for(JoinDescriptor JoinDescriptor:joinDescriptors)
join(joinDescriptor,query);
返回query.where(谓词);
}
专用JPQLQuery连接(JoinDescriptor JoinDescriptor,JPQLQuery查询){
开关(joinDescriptor.type){
案例默认值:
抛出新的IllegalArgumentException(“不支持交叉连接”);
案例内部连接:
innerJoin(joinDescriptor.path);
打破
案例连接:
join(joinDescriptor.path);
打破
案例LEFTJOIN:
leftJoin(joinDescriptor.path);
打破
案例RIGHTJOIN:
query.rightJoin(joinDescriptor.path);
打破
案例完整连接:
query.fullJoin(joinDescriptor.path);
打破
}
返回query.fetch();
}
}
工厂创建自定义存储库,替换默认的QueryDslJpaRepository

@NoRepositoryBean
public interface JoinFetchCapableRepository<T, ID extends Serializable> extends     JpaRepository<T, ID>, QueryDslPredicateExecutor<T> {

    Page<T> findAll(Predicate predicate, Pageable pageable, JoinDescriptor... joinDescriptors);
}
public class JoinFetchCapableRepositoryImpl <T, ID extends Serializable> extends QueryDslJpaRepository<T, ID> implements JoinFetchCapableRepository<T, ID> {

    private static final EntityPathResolver DEFAULT_ENTITY_PATH_RESOLVER = SimpleEntityPathResolver.INSTANCE;

    private final EntityPath<T> path;
    private final PathBuilder<T> builder;
    private final Querydsl querydsl;

    public JoinFetchCapableRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager) {
        this(entityInformation, entityManager, DEFAULT_ENTITY_PATH_RESOLVER);
    }

    public JoinFetchCapableRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager, EntityPathResolver resolver) {
        super(entityInformation, entityManager, resolver);
        this.path = resolver.createPath(entityInformation.getJavaType());
        this.builder = new PathBuilder<>(path.getType(), path.getMetadata());
        this.querydsl = new Querydsl(entityManager, builder);
    }

    @Override
    public Page<T> findAll(Predicate predicate, Pageable pageable, JoinDescriptor... joinDescriptors) {
        JPQLQuery countQuery = createQuery(predicate);
        JPQLQuery query = querydsl.applyPagination(pageable, createFetchQuery(predicate, joinDescriptors));

        Long total = countQuery.count();
        List<T> content = total > pageable.getOffset() ? query.list(path) : Collections.<T> emptyList();

        return new PageImpl<>(content, pageable, total);
    }

    protected JPQLQuery createFetchQuery(Predicate predicate, JoinDescriptor... joinDescriptors) {
        JPQLQuery query = querydsl.createQuery(path);
        for(JoinDescriptor joinDescriptor: joinDescriptors)
            join(joinDescriptor, query);
        return query.where(predicate);
    }

    private JPQLQuery join(JoinDescriptor joinDescriptor, JPQLQuery query) {
        switch(joinDescriptor.type) {
            case DEFAULT:
                throw new IllegalArgumentException("cross join not supported");
            case INNERJOIN:
                query.innerJoin(joinDescriptor.path);
                break;
            case JOIN:
                query.join(joinDescriptor.path);
                break;
            case LEFTJOIN:
                query.leftJoin(joinDescriptor.path);
                break;
            case RIGHTJOIN:
                query.rightJoin(joinDescriptor.path);
                break;
            case FULLJOIN:
                query.fullJoin(joinDescriptor.path);
                break;
        }
        return query.fetch();
    }
}
public class JoinFetchCapableQueryDslJpaRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable>
        extends JpaRepositoryFactoryBean<R, T, I> {

    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {

        return new JoinFetchCapableQueryDslJpaRepositoryFactory(entityManager);
    }
    private static class JoinFetchCapableQueryDslJpaRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory {

        private EntityManager entityManager;

        public JoinFetchCapableQueryDslJpaRepositoryFactory(EntityManager entityManager) {
            super(entityManager);
            this.entityManager = entityManager;
        }

        protected Object getTargetRepository(RepositoryMetadata metadata) {
            return new JoinFetchCapableRepositoryImpl<>(getEntityInformation(metadata.getDomainType()), entityManager);
        }

        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
            return JoinFetchCapableRepository.class;
        }
    }
}
公共类JoinFetchCapableQueryDslJpaRepositoryFactoryBean
扩展JpaRepositoryFactoryBean{
受保护的RepositoryFactorySupport createRepositoryFactory(EntityManager EntityManager){
返回新的JoinFetchCapableQueryDslJpaRepositoryFactory(entityManager);
}
私有静态类JoinFetchCapableQueryDslJpaRepositoryFactory扩展了JpaRepositoryFactory{
私人实体管理者实体管理者;
public JoinFetchCapableQueryDslJpaRepositoryFactory(EntityManager EntityManager){
超级(实体管理器);
this.entityManager=entityManager;
}
受保护对象GetTargetPository(RepositoryMetadata元数据){
返回新的JoinFetchCapableRepositoryImpl(getEntityInformation(metadata.getDomainType()),entityManager);
}
受保护类getRepositoryBaseClass(RepositoryMetadata元数据){
返回JoinFetchCapableRepository.class;
}
}
}
最后一步是更改jpa配置,使其使用此工厂而不是默认工厂:

<jpa:repositories base-package="com.mycompany.repository"
                      entity-manager-factory-ref="entityManagerFactory"
                      factory-class="com.mycompany.utils.spring.data.JoinFetchCapableQueryDslJpaRepositoryFactoryBean" />

然后,您可以从服务层使用它,如下所示:

public Page<ETicket> list(ETicketSearch eTicket, Pageable pageable) {
    return eticketRepository.findAll(like(eTicket), pageable, JoinDescriptor.leftJoin(QETicket.eTicket.order));
}
公共页面列表(ETicketSearch eTicket,Pageable Pageable){
返回eticketRepository.findAll(如(eTicket),可分页,JoinDescriptor.leftJoin(qetick.eTicket.order));
}
通过使用JoinDescriptor,您将能够根据您的服务需求指定要加入的内容


多亏了Murali在这里的回复:请看一看。

春季数据。注意这一点

如果这是可能的,你是什么意思
Querydsl谓词执行器
提供了Querydsl功能的一小部分,您需要自己编写更多的查询。是的,我知道,但我正试图想出一种避免这种情况的方法,使用谓词API构建更复杂的查询,允许我随意获取关系,附加其他谓词,因此,不必为存储库界面中的特定目的创建带有注释查询的方法。谢谢您的回答。虽然我最终使用了Criteria方法,但我将在一个较小的项目上测试这种方法,我有一个用于测试东西的项目。谢谢你的努力…嗨,谢谢你的回答。是否可以扩展JoinDescriptor以包括o