Grails中read()获取Domain后save()无法持久化属性(版本号已更新)
解决Grails中read()获取实例后属性无法持久化的问题
我之前也踩过这个坑,咱们来理清楚问题出在哪以及怎么解决:
核心原因:read()方法的只读特性
Grails里的read()方法获取的Domain实例是只读模式的——它只会加载实例的当前状态和版本号,但默认不会开启Hibernate的属性变化追踪机制。这就导致你修改属性后调用save(),GORM只会执行乐观锁的版本号更新(所以你看到version字段变了),但不会生成更新其他属性的SQL,自然修改就没持久化到数据库。
两种可行的解决方案
方案1:改用get()方法获取实例
get()方法会获取完全的持久化实例,自动开启属性变化追踪,修改后直接save就能正常持久化所有变更:
class AdhocChargeTypeController { def testRead(Long id) { // 用get()替代read(),获取可追踪变化的实例 AdhocChargeType adHocChargeType = AdhocChargeType.get(id) // 修改属性 adHocChargeType.adHocChargeType = "Updated One-Time Charge" adHocChargeType.glCode = "GL-ADHOC-002" // 建议添加flush:true确保立即持久化,同时处理保存失败的情况 if (adHocChargeType.save(flush: true, failOnError: true)) { // 保存成功后的逻辑,比如返回成功响应 render "Charge type updated successfully" } } }
方案2:对read()获取的实例调用attach()
如果业务场景必须用read()(比如只是偶尔需要修改,大部分时候只读),可以调用attach()方法把只读实例转为持久化状态,开启变化追踪后再修改属性:
class AdhocChargeTypeController { def testRead(Long id) { AdhocChargeType adHocChargeType = AdhocChargeType.read(id) // 将只读实例转为可追踪的持久化实例 adHocChargeType.attach() // 修改属性 adHocChargeType.adHocChargeType = "Updated One-Time Charge" adHocChargeType.glCode = "GL-ADHOC-002" if (adHocChargeType.save(flush: true, failOnError: true)) { render "Charge type updated successfully" } } }
额外说明
你看到version字段更新是因为:即使实例是只读的,save()方法依然会触发乐观锁校验,自动递增version字段,但由于没有属性变化被追踪,所以只有version的更新会被执行到数据库。
内容的提问来源于stack exchange,提问作者Kalpana
相关产品推荐
相关产品推荐

