NonUniqueResultException: JPARepository 春季启动
Posted
技术标签:
【中文标题】NonUniqueResultException: JPARepository 春季启动【英文标题】:NonUniqueResultException: JPARepository Spring boot 【发布时间】:2018-12-11 13:00:23 【问题描述】:我将SpringBoot
与JPA
和QueryDSL
一起使用。我写了一个HQL
来从表中获取一些自定义记录,但它正在抛出Exception
。下面我提到存储库的代码:
@Repository
public interface LoanOfferRepository extends JpaRepository<LoanOffer, Long>, QuerydslPredicateExecutor<LoanOffer>
@Query("select lo.startDate,count(*) from LoanOffer lo where lo.loan.fsp= :fsp and lo.startDate between :fromDate and :toDate Group by lo.startDate")
public Map<LocalDate,Integer> getLastMonthLoans(@Param("fsp")Fsp fsp,@Param("fromDate")LocalDate fromDate,@Param("toDate")LocalDate toDate);
每当我调用此方法getLastMonthLoans()
时,我都会收到以下异常:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.IncorrectResultSizeDataAccessException: query did not return a unique result: 9; nested exception is javax.persistence.NonUniqueResultException: query did not return a unique result: 9] with root cause
javax.persistence.NonUniqueResultException: query did not return a unique result: 9
代码或查询或返回类型有什么问题吗?查询似乎工作正常。
【问题讨论】:
你应该使用projections。请检查我的答案1,2 如何从 repo 返回任意对象。 【参考方案1】:您的查询结果无法映射到Map<LocalDate,Integer>
。
您可以尝试返回List<Object[]>
而不是Map
。
@Query("select lo.startDate,count(*) from LoanOffer lo where lo.loan.fsp= :fsp and lo.startDate between :fromDate and :toDate Group by lo.startDate")
public List<Object[]> getLastMonthLoans(@Param("fsp")Fsp fsp,@Param("fromDate")LocalDate fromDate,@Param("toDate")LocalDate toDate);
然后将List<Object[]>
解析成你需要的Map
。
这样:
Map<LocalDate, Integer> mappedResult = new HashMap<>();
List<Object[]> queryResult = loanOfferRepository.getLastMonthLoans(fsp, fromDate, toDate);
for (Object[] obj : queryResult )
LocalDate ld = (LocalDate) obj[0];
Integer count = (Integer) obj[1];
mappedResult.put(ld, count);
【讨论】:
【参考方案2】:根据 Spring Data 文档,Map
不属于 Supported Query Return Types。
甚至 JPA(甚至是 2 版本)也不支持 Map
作为执行查询中的返回类型。
所以你有两种方法可以解决你的问题:
1) 保留Map
作为返回类型。在这种情况下,不要使用 Spring Data 特性,它可以让您免于编写样板代码。
而是:从 EntityManager
创建查询,执行它并应用后处理将结果映射到 Map。
如果Map
具有合理的大小,并且您确实需要从存储库中检索Map
,则应该优先使用这种方式。
2) 不要返回 Map
作为返回类型。
在这两种情况下,您都必须选择执行查询的返回类型。您大致有两种选择:
1) List<Object[]>
作为返回类型,但它不一定有意义,也不是类型安全的。
2) 表示行结构的自定义类
public class LoanOfferStats
private LocalDate startDate;
private Long count;
public LoanOfferStats(LocalDate startDate, Long count)
this.startDate = startDate;
this.count = count;
public LocalDate getStartDate()
return startDate;
public Long getCount()
return count;
并注释您的方法,例如:
@Query("select new fullpackage.LoanOfferStats(lo.startDate,count(*))
from LoanOffer lo where lo.loan.fsp= :fsp and lo.startDate between
:fromDate and :toDate Group by lo.startDate")
public List<LoanOfferStats> getLastMonthLoans(@Param("fsp")Fsp fsp,@Param("fromDate")LocalDate fromDate,@Param("toDate")LocalDate
toDate);
请注意,在 Java 8 中将 List
转换为 Map
非常直接:
List<LoanOfferStats> loanOfferStats = loanOfferRepository.getLastMonthLoans(...);
Map<LocalDate, Long> map =
loanOfferStats.stream()
.collect(Collectors.toMap(LoanOfferStats::getStartDate, LoanOfferStats::getCount));
【讨论】:
以上是关于NonUniqueResultException: JPARepository 春季启动的主要内容,如果未能解决你的问题,请参考以下文章
如何解决此问题 org.hibernate.NonUniqueResultException:查询未返回唯一结果:4
查询未返回唯一结果:4;嵌套异常是 javax.persistence.NonUniqueResultException:查询没有返回唯一结果:4