使用JPQL时发生Spring JPA存储库转换错误

使用JPQL时发生Spring JPA存储库转换错误,jpa,spring-data,Jpa,Spring Data,我声明了一个分页和排序JPA存储库。我正在使用@Query注释 当我从存储库的findById(id)方法对可选对象调用get()方法时,我遇到了一个异常 奇怪的是,只有在我使用JPQL时才会发生这种情况 如果我的查询是本机查询,则代码有效: @Override public BatchDto findById(String id) { Optional<Batch> findResult = this.batchRepository.findById(id);

我声明了一个分页和排序JPA存储库。我正在使用@Query注释

当我从存储库的findById(id)方法对可选对象调用get()方法时,我遇到了一个异常

奇怪的是,只有在我使用JPQL时才会发生这种情况

如果我的查询是本机查询,则代码有效:

    @Override
public BatchDto findById(String id) {
    Optional<Batch> findResult =  this.batchRepository.findById(id);
    if (!findResult.isPresent()) return null;
    Batch entity = findResult.get();  **<-------- Cast Exception Here**
    BatchDto dto = this.mapper.toDto(entity, BatchDto.class);
    List<BatchTransaction> transactions = entity.getTransactions();
    dto.setTransactionDtos(mapper.toListDto(transactions, TransactionDto.class));
    return dto;
}
当@Query注释中有nativeQuery=true时

@Query(value = Sql.FindBatchById, nativeQuery = true) 
以下是正在使用的查询:

SELECT DISTINCT(B.batchNumber), COUNT(B.batchNumber) as TransactionCount FROM BATCH B WHERE B.batchReferenceNumber = :id GROUP BY B.batchNumber
但是,如果我将其更改为JPQL并删除nativeQuery=true属性,则findResult是

Optional[[Ljava.lang.Object;@76e04327].  
我得到一个ClassCastException:

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to net.domain.data.batch
所以底线-当指定nativeQuery=true时,这是有效的,当我尝试使用JPQL时,这是失败的


我不希望指定nativeQuery,因为我们最终将把这个数据库移植到Oracle

首先,下面显示的查询不会返回单个
Batch
实例。由于有
distinct
count
聚合函数,因此查询将返回聚合的
列表。
为了能够读取这些统计数据,您可以将适当的方法添加到batchRepository中。大概是这样的:

@Query("SELECT DISTINCT(B.batchNumber) as dist, COUNT(B.batchNumber) as cnt FROM BATCH B GROUP BY B.batchNumber")
  List<Map<Long, Long>> findStatistics();

方法
this.batchRepository.findById(id)的内容是什么?您没有显示JPQL。已添加查询。该查询返回两列,而不是批处理实例。所以你得到了一个对象数组。这是意料之中的。为什么您认为它应该返回批处理的实例?只有当您的查询是
从批处理b中选择b,其中…
,它才会这样做。那么为什么使用natvieSql进行强制转换会起作用呢?它成功地将结果集中的列映射到批处理对象中,因为SQL没有实体的概念,而JPQL有实体的概念。因此,当您明确选择不使用JPQL选择实体,而是选择两个值时,它不会选择实体,而是返回两个值。
@Query("SELECT DISTINCT(B.batchNumber) as dist, COUNT(B.batchNumber) as cnt FROM BATCH B GROUP BY B.batchNumber")
  List<Map<Long, Long>> findStatistics();
@Query("SELECT DISTINCT(B.batchNumber) as dist, COUNT(B.batchNumber) as cnt FROM BATCH B WHERE B.batchReferenceNumber = :id GROUP BY B.batchNumber")
      Map<Long, Long> findStatisticsById(@Param("id") Long id);