Spring Boot JPA只读查询导出数据时@Version标注版本号自动递增问题
问题原因排查与解决方案
你遇到的只读查询触发版本号递增的核心原因是JPA检测到查询返回的托管态实体存在属性变更,事务提交时自动执行了脏数据刷入操作,连带触发了@Version注解的版本号递增逻辑,具体原因和对应修复方案如下:
核心触发原因
- 方法未配置只读事务:默认情况下Spring事务为读写模式,查询返回的实体会被持久化上下文托管,只要实体属性和数据库存储值不一致就会被标记为脏数据,事务提交时自动执行更新
- 实体默认值与数据库字段不匹配:你代码中
BaseEntity的deleted字段设置了默认值0,如果数据库中该字段允许为null、且历史数据的deleted值为null,查询时JPA会自动将实体的deleted属性赋值为0,导致和数据库原值不一致,被判定为脏数据 - 审计配置异常:如果开启了
@EnableJpaAuditing,异常的审计切面逻辑可能会在只读场景下错误填充@LastModifiedDate字段,导致实体属性变更
修复方案
- 给导出方法添加只读事务注解
在exportData方法上添加@Transactional(readOnly = true),该配置会让持久化上下文进入只读模式,不会检测实体脏数据,也不会执行任何更新操作:@Transactional(readOnly = true) public void exportData(){ List<ChildEntiy> list=repository.getChildDetails(); for(ChildEntity child:list){ responseDto=child.getDisplayName(); } } - 对齐实体属性默认值与数据库约束
要么将数据库DELETED字段设置为非空、默认值为0,要么删除实体类中deleted的默认值赋值,避免查询时属性值和数据库不一致 - 给查询方法添加只读查询提示
在Repository的getChildDetails方法上添加只读查询hint,让返回的实体直接为游离态,不被持久化上下文跟踪:@QueryHints(value = @QueryHint(name = org.hibernate.jpa.QueryHints.HINT_READ_ONLY, value = "true")) List<ChildEntity> getChildDetails();
内容的提问来源于stack exchange,提问作者Vaibhav
相关产品推荐
相关产品推荐

