繁体   English   中英

在查询DSL + Spring Data JPA中进行分组,并抛出NoSuchElementException

[英]Group by in Query DSL + Spring Data JPA throwing NoSuchElementException

我正在尝试使用Spring Data JPA和Query DSL按组执行查询。

但是,我得到以下异常:

org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'japanWHTDaoImpl': 
   Unsatisfied dependency expressed through field 'wht21940000DataRepo'; 
       nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'japanWHT21940000DataRepository': 
    Invocation of init method failed; nested exception is java.util.NoSuchElementException

我试图编写自定义存储库实现,并在下面的接口和impl类中给出以下信息:

自定义界面:

public interface JapanWHT21940000DataRepositoryCustom {
        List<WHT21940000Royalties> findLocalCcyAmtsByRemarks();
}

自定义Impl类:

@Repository
@Transactional
public class JapanWHT21940000DataRepositoryCustomImpl extends QueryDslRepositorySupport implements JapanWHT21940000DataRepositoryCustom {

    public JapanWHT21940000DataRepositoryCustomImpl(Class<?> domainClass) {
    super(domainClass);
    // TODO Auto-generated constructor stub
    }

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public List<WHT21940000Royalties> findLocalCcyAmtsByRemarks() {
    QWHT21940000Data wht21940000Data = QWHT21940000Data.wHT21940000Data;
    JPAQuery<WHT21940000Royalties> query = new JPAQuery<WHT21940000Royalties>(entityManager);
    query.from(wht21940000Data).groupBy(wht21940000Data.remarks).select(wht21940000Data.remarks, wht21940000Data.localCcyAmt.sum());

    return null;
    }

}

Spring数据JPA接口:

public interface JapanWHT21940000DataRepository
    extends JpaRepository<WHT21940000Data, Long>, 
        QueryDslPredicateExecutor<WHT21940000Data>, 
        JapanWHT21940000DataRepositoryCustom {

}

在DAO类中:

@Repository
@Transactional("japanWhtTransactionManager")
public class JapanWHTDaoImpl implements JapanWHTDao {
    @Autowired
    JapanWHT21940000DataRepository wht21940000DataRepo;
    // more code to follow...

编辑:还是有比我正在尝试的方法更简单更好的方法来按Spring数据JPA +查询DSL进行分组查询?

我认为真正的问题是从JpaRepositories执行定制的querydsl查询,尽管我建议使用定制的扩展基础存储库类,如下所示。

首先,扩展基础存储库类。

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

    <T1> Page<T1> findAll(JPQLQuery jpqlQuery, Pageable pageable);
}

和相关的实现。

public class ExtendedQueryDslJpaRepositoryImpl<T, ID extends Serializable>
    extends QueryDslJpaRepository<T, ID> implements ExtendedQueryDslJpaRepository<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;

    private EntityManager entityManager;

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

    public ExtendedQueryDslJpaRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager, EntityPathResolver
        resolver) {

        super(entityInformation, entityManager);
        this.path = resolver.createPath(entityInformation.getJavaType());
        this.builder = new PathBuilder(this.path.getType(), this.path.getMetadata());
        this.querydsl = new Querydsl(entityManager, this.builder);
        this.entityManager = entityManager;
    }

    @Override
    public <T1> Page<T1> findAll(JPQLQuery jpqlQuery, Pageable pageable) {

        final JPQLQuery<?> countQuery = jpqlQuery;

        JPQLQuery<T1> query = querydsl.applyPagination(pageable, jpqlQuery);

        return PageableExecutionUtils.getPage(query.fetch(), pageable, countQuery::fetchCount);
    }
}

上面的类可以放在配置包中。

然后,我们将ExtendedQueryDslJpaRepositoryImpl定义为JpaRepository类应从其ExtendedQueryDslJpaRepositoryImpl默认类,如下所示:

@Configuration
@EnableJpaRepositories(basePackageClasses = Application.class, repositoryBaseClass = ExtendedQueryDslJpaRepositoryImpl.class)
public class JpaConfig {

    @PersistenceContext
    private EntityManager entityManager;

    @Bean
    public JPAQueryFactory jpaQueryFactory() {
        return new JPAQueryFactory(entityManager);
    }
}

下一步是为应用程序的Entity定义存储库,例如。 CustomEntity

public interface CustomRepository extends ExtendedQueryDslJpaRepository<CustomEntity, Long>, CustomRepositorySupport {
}

接下来,我们为自定义方法定义定义接口CustomRepositorySupport

public interface CustomRepositorySupport {

    JPQLQuery<CustomListDto> createCustomIndexQuery();
}

最后是自定义存储库实现。

@Repository
public class CustomRepositoryImpl implements CustomRepositorySupport {

    private JPAQueryFactory queryFactory;

    @Autowired
    public CustomRepositoryImpl(JPAQueryFactory queryFactory) {
        this.queryFactory = queryFactory;
    }

    @Override
    public JPQLQuery<CustomListDto> createCustomIndexQuery() {

        QCustomEntity qCustomEntity = QCustomEntity.customEntity;

        BooleanBuilder predicate = new BooleanBuilder();

        // Create predicate as desired
        // predicate.and(...);

        // Create projection of fields
        /* FactoryExpression<CustomListDto> factoryExpression = Projections.bean(CustomListDto.class,
            qCustomEntity.fieldA,
            qCustomEntity.fieldB,
            qCustomEntity.fieldC,
            qCustomEntity.fieldD,
            qCustomEntity.fieldE,
            qCustomEntity.fieldF); */

        return queryFactory.from(qCustomEntity).select(factoryExpression).where(predicate);
    }
}

最后一步是从Service类实际调用该方法,如下所示。

public interface CustomFinder {

    Page<CustomListDto> findIndex(Pageable pageable);
}

--

@Service
public class CustomFinderImpl implements CustomFinder {

    private CustomRepository customRepository;

    @Autowired
    public CustomFinderImpl(CustomRepository customRepository) {
        this.customRepository = customRepository;
    }

    @Override
    public Page<CustomListDto> findIndex(Pageable pageable) {

        JPQLQuery<CustomListDto> query = customRepository.createCustomIndexQuery();

        return customRepository.findAll(query, pageable);
    }
}

与我们实现public <T1> List<T1> findAll(JPQLQuery query, FactoryExpression<T1> factoryExpression) ,我们可以简单地实现所需的所需方法,如public <T1> List<T1> findAll(JPQLQuery query, FactoryExpression<T1> factoryExpression) <T1> List<T1> findList(JPQLQuery query, FactoryExpression<T1> factoryExpression)

这样,我们为所有存储库添加了功能,以便利用所有类型的querydsl查询,而不仅是group byprojections

它看起来似乎有些复杂,但是如果您选择实现它,并查看它如何工作,则您会坚持下去。 它已在实际应用程序中成功使用,可以访问投影查询(无需在不需要它们的情况下加载完整实体),分页查询,存在子查询等。

最后,使用一种中央基础存储库类是一种仅可编写一次的可重用代码。

希望能有所帮助。

暂无
暂无

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

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