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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:26:52