You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Service注入JPA实体监听器以解决审计数据存储时空指针异常问题

问题原因

JPA实体监听器的实例是由JPA provider(比如Hibernate)自行创建的,不受Spring容器管理,因此你在监听器里加的@Autowired注解不会被Spring解析执行,静态的auditService始终为null,调用时就会抛出空指针异常。

解决方案

方案1:通过Spring上下文工具类手动获取Bean(兼容性最好)

  1. 首先创建Spring上下文持有工具类:
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringContextHolder implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextHolder.applicationContext = applicationContext;
    }

    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }
}
  1. 修改AuditTrailListener,使用时主动从上下文获取Bean:
public class AuditTrailListener {

    @PrePersist
    @PreUpdate
    @PreRemove
    private void beforeAnyUpdate(User user) {
        System.out.println(user);
        SpringContextHolder.getBean(AuditService.class).saveOrUpdate(new AuditObject());
    }
    
    @PostPersist
    @PostUpdate
    @PostRemove
    private void afterAnyUpdate(User user) {
        System.out.println(user);
        SpringContextHolder.getBean(AuditService.class).saveOrUpdate(new AuditObject());
    }
    
    @PostLoad
    private void afterLoad(User user) {
        System.out.println(user);
        SpringContextHolder.getBean(AuditService.class).saveOrUpdate(new AuditObject());
    }
}

方案2:配置Hibernate使用Spring Bean容器(Spring Boot环境推荐)

  1. 给AuditTrailListener添加@Component注解,交给Spring托管
  2. 在application.yml/application.properties中添加配置:
spring:
  jpa:
    properties:
      hibernate:
        resource:
          beans:
            container:
              spi: org.springframework.orm.hibernate5.SpringBeanContainer

配置完成后Hibernate会从Spring容器中获取监听器实例,@Autowired就可以正常注入了。

其他需要修正的代码问题

  • AuditService的saveOrUpdate方法参数类型为Audit,但实际调用时传入的是AuditObject,需要统一类型,将方法签名改为public AuditObject saveOrUpdate(AuditObject auditObject)
  • AuditObject的id属性类型为int,但赋值为1L,且AuditRepository的主键泛型为Long,需要统一主键类型:将AuditObject的id改为private Long id;即可

内容的提问来源于stack exchange,提问作者John Friday

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 09:09:03