一个空的结果集上的Spring Data JPA聚合函数

我正在从事一个涉及Spring和JPA / Hibernate的项目.我的开发环境中使用的数据库驱动程序是H2.我的应用程序有一个显示统计信息的页面,这种统计信息的一个示例是用户的平均年龄.但是,当我尝试使用JPQL获取平均年龄时,会收到一个异常

Result must not be null!

为简单起见,假设我将年龄作为整数存储在每个User对象上(在我的应用程序中当然不是这种情况,但这对我的问题并不重要).

用户模型

@Entity
public class User implements Identifiable<Long> {
    private int age;
    // more fields and methods, irrelevant
}

用户资料库

@Repository
public interface UserRepository extends CrudRepository<User, Long> {
    @Query("SELECT AVG(u.age) FROM #{#entityName} u")
    long averageAge();
}

我似乎无法弄清楚为什么要调用UserRepository#averageAge();引发异常.我尝试用COUNT替换查询中的函数AVG,其行为与预期的一样.我也尝试过使用SQL查询,并在注释中设置nativeQuery = true,但无济于事.我当然可以通过获取所有用户并计算纯Java语言的平均年龄来解决此问题,但这并不是很有效.

堆栈跟踪:

Caused by: org.springframework.dao.EmptyResultDataAccessException: Result must not be null!
    at org.springframework.data.repository.core.support.MethodInvocationValidator.invoke(MethodInvocationValidator.java:102)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
    at com.sun.proxy.$Proxy150.averageAge(Unknown Source)
    at my.test.application.StatisticsRunner.run(StatisticsRunner.java:72)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:809)
    ... 30 more

解决了

该异常是由于在空表上执行时AVG()返回null引起的.我通过修改查询(受the answer to this question启发)来解决此问题,如下所示:

@Query("SELECT coalesce(AVG(u.age), 0) FROM #{#entityName} u")
long averageAge();

解决方法:

似乎当查询的结果预期至少具有一行(或元素)但未返回任何行时,将引发EmptyResultDataAccessException异常.

有关此内容的相关文档,请参见here.

我建议运行与尝试运行相同的查询,以进一步验证该理论.现在,好问题是如何处理.

您有两个选择.在您的调用点捕获EmptyResultDataAccessException异常并直接在其中处理它,或者您可以拥有一个ExceptionHandler,它将负责处理此类异常.

两种处理方式都应该可以,您可以根据自己的情况在两者之间进行选择.

上一篇:java-H2 DB:如何检查表模式是否以编程方式初始化?


下一篇:java-在sql2o中插入时出错