Spring Data JPA继承父类的Date审计字段执行更新不生效如何解决
问题原因
Spring Data JPA的审计功能(包括@LastModifiedDate、@LastModifiedBy注解的自动填充)依赖AuditingEntityListener,而该监听器只会在JPA实体的生命周期回调(比如save、update操作触发的实体持久化)时执行。你写的自定义JPQL UPDATE语句属于直接操作数据库的批量更新逻辑,会跳过所有实体生命周期回调,所以审计字段不会自动更新,你手动传lastUpdatedOn也只处理了日期,没处理操作人字段。
解决方案
方案1:先查询再修改保存(推荐)
这种方式可以自动触发审计逻辑,不需要手动处理审计字段和版本号,还能保证乐观锁正常生效:
- 先根据ID查询出对应的Employee实体
- 修改实体的status字段
- 调用JpaRepository自带的
save()方法保存
代码示例:
@Transactional public void updateEmployeeStatus(Long id, String status) { // 查询实体 Employee employee = employeeRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("对应员工ID不存在:" + id)); // 修改业务字段 employee.setStatus(status); // 保存时自动触发审计字段、版本号更新 employeeRepository.save(employee); }
方案2:保留JPQL批量更新,手动补充所有字段
如果业务场景需要用批量更新提高性能,你需要手动传入所有需要更新的审计字段、手动处理版本号递增:
修改后的Repository方法:
@Modifying(clearAutomatically = true, flushAutomatically = true) @Transactional @Query("UPDATE Employee p SET p.status =:status, p.lastUpdatedOn = :updateTime, p.lastUpdatedByUser = :operator, p.versionNumber = p.versionNumber + 1 WHERE p.srcProjectKeyId = :id") int updateStatus(@Param("status") String status, @Param("id") Long id, @Param("updateTime") Date updateTime, @Param("operator") String operator);
调用方法时,自行传入当前时间new Date()和当前登录用户的账号作为操作人即可。
前置检查
确认你的Spring Boot启动类上已经添加了@EnableJpaAuditing注解开启审计功能,否则所有审计字段的自动填充逻辑都不会生效:
@SpringBootApplication @EnableJpaAuditing public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }
内容的提问来源于stack exchange,提问作者Jeff Cook
相关产品推荐
相关产品推荐

