Grails:尝试使用嵌套对象保存对象。没有错误但没有 ID

Grails: Try to save a object with nested objects. No error but no ID

这是我的应用程序:我的用户由三个元素组成

  1. User(用户名、密码、角色等。来自 SpringSecurity)
  2. AppUser(姓氏等基本信息)
  3. Detail User(按应用程序、工作区域等指定的详细信息)

AppUser 包含 User 和 DetailUser 的实例(最后一个可为空)

这是我的代码:

 if (user.validate() &&  appUser.validate() ){
            user.save()
            appUser.user = user
            appUser.save()

            appUserDetail.appUser = appUser
            appUserDetail.save()

        }

没有错误验证,但我的 appUser 的 ID 为空!

真诚地 我不明白为什么。

更新

Hibernate.AssertionFailure an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
org.hibernate.AssertionFailure: null id in it.geny.auth.AppUser entry (don't flush the Session after an exception occurs)

首先,在没有 failOnError: true.save() 上不会出现任何错误 即

user.save(failOnError: true)

它只会悄悄地不保存,也不会真正通知它失败了(如果你想看到失败,你必须检查它是否包含错误)。

最后,该特定错误出现在大量与正在创建连接表的保存有关的事件中。

我所见过的最好的情况是您要确保父项和子项都具有相互返回的链接。所以,你想做这样的事情:

 if (user.validate() &&  appUser.validate() ){
        user.appUser = appUser
        appUser.user = user
        appUserDetail.appUser = appUser
        appUser.UserDetail = appUserDetail

        appUserDetail.save(failOnError: true)
        appUser.save(failOnError: true)
        user.save(failOnError: true)

    }

我没有测试这段代码,您可能需要稍微调整一下,但关键是您要确保每个对象在保存之前都指向另一个对象。

failOnError 可能不是必需的,您可能不希望在保存失败时抛出异常,在这种情况下您可以调用 .save() 然后检查 user.errors对于给定的错误。通常我在我的 gsp 中使用 g:eachError 标签向最终用户显示错误,这样他们就可以清理提交并重试。

终于找到解决方法了

在 SO 上搜索有关此问题的信息,我发现了很多 post。有人说:

<Domain>.get(id)

也许可以关闭会话,因为对象不会被保存。 但是我在哪里调用 .get 函数?!?!?

这里:

def appUser = new AppUser(params)

在内部我有一个一对一的 rel 到许多 domanins(例如 Region region)。在 GrailsParameterMap 中,我有 params."appUser.region" 和区域 ID。

如果我使用 grails 的活页夹 (spring)(我无法检查代码,但如果这是真的,我会在某处找到一个 .get(id)...),我的对象将不会坚持。

但是,如果我手动绑定,一切正常,我的对象被保存了。