0

我正在将 Grails 应用程序从 Oracle 移植到 MySQL 数据库。最初的 Oracle 版本是一个遗留数据库,它使用一些复杂的视图来利用 MySQL 所没有的 Oracle 的 INSTEAD OF INSERT OR UPDATE 特性。作为一种解决方法,我在指向这些视图的域类上实现了插入和更新方法。例如,

class AdminUser {
    //...
    def update() {
        if(this.validate()) {
            Sql sql = Utils.getHibernateSql()

            sql.execute(
                "update table_x ...",
                [...]
            )

            sql.execute(
                "update table_y ...)",
                [...]
            )

            sql.execute(
                "update table_z ...",
                [...]
            )

            return true
        }

        return false
    }
    //...
}

以下是我目前遇到的问题的描述:

  1. 在服务方法中,我使用 AdminUser.get 加载 AdminUser 的实例
  2. 我修改加载的实例并调用update(),一切正常
  3. 一旦服务方法完成执行,由于在实例上调用 save 的东西而引发异常。

如何防止在步骤 (3) 中发生神奇的保存(我最近在某处读到 Grails 会自动保存已修改的 Domain 类实例,该实例在退出服务方法时尚未保存,但我似乎找不到现在链接到该资源)?

4

2 回答 2

2

您将修改后的实例留在带有脏字段的休眠会话中。当休眠会话被刷新时,它将尝试使用通常的save()方法再次保存对象。

一种解决方案是在您手动保存更改后从休眠会话中丢弃您的对象。例如:

def update() {
    if(this.validate()) {
        Sql sql = Utils.getHibernateSql()

        sql.execute(
            "update table_z ...",
            [...]
        )

        ...

        this.discard()  // remove the object from the hibernate session
        return true
    }

此外,您可以将其添加到 Config.groovy 以要求明确保存对象:

hibernate.flush.mode="manual"
于 2010-10-12T17:36:50.413 回答
0

If you use read() instead of get(), then the object will not auto-persist changes. You can still call save() explicitly, but the standard behavior where the OpenSessionInView interceptor flushes all unsaved dirty instances will skip the instances loaded with read().

于 2010-10-12T17:50:27.827 回答