SpringBoot调用Repository的@Query方法获取查询结果时报空指针异常
问题排查与解决方案
核心原因分析
- 你代码中用到的
@PrePersist、@PreUpdate属于JPA实体生命周期回调注解,这类回调对应的实例默认由Hibernate等JPA实现直接创建,不受Spring容器管理,因此类内标注的@Autowired不会生效,你拿到的demoRepository本身就是空对象,调用方法时就会出现异常或者返回null。 - 次要排查点:当数据库中
DemoStudentData表没有数据时,SUM聚合函数的返回值本身就是null,这属于SQL的正常行为,如果是首次插入数据的场景,@PrePersist执行时新数据还未落库,也会触发该情况。
对应解决方案
方案1:开启实体监听器的Spring注入能力
如果你是将SampleMarksValues作为实体监听器使用(即DemoStudentData类上标注了@EntityListeners(SampleMarksValues.class)),可以通过Spring的AspectJ织入能力实现非Spring管理实例的依赖注入:
- 给
SampleMarksValues类添加@Configurable注解 - 项目引入AOP依赖,Spring Boot项目直接添加
spring-boot-starter-aop即可 - 在项目配置类上添加
@EnableSpringConfigured注解,开启注入支持
方案2:手动从Spring上下文获取Repository实例
不需要修改AOP配置,通过工具类主动获取Bean,兼容性更强:
- 新增Spring上下文工具类:
@Component public class SpringContextHolder implements ApplicationContextAware { private static ApplicationContext context; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { context = applicationContext; } public static <T> T getBean(Class<T> beanClass) { return context.getBean(beanClass); } }
- 修改回调方法的逻辑,手动获取Repository实例:
@PreUpdate @PrePersist public void useTotalMarks(DemoStudentData demo) { DemoRepository repo = SpringContextHolder.getBean(DemoRepository.class); Double marks = repo.totalMarks(); demo.setTotal_Marks(marks); }
额外优化:避免SUM返回null
修改Repository层的查询语句,用COALESCE函数处理空值,无数据时默认返回0:
@Query("SELECT COALESCE(SUM(dt.demo_marks), 0) FROM DemoStudentData dt") Double totalMarks();
内容的提问来源于stack exchange,提问作者Kumar_Maddy
相关产品推荐
相关产品推荐

