Java Grails以一对一的关联替换对象

Java Grails以一对一的关联替换对象,java,hibernate,grails,gorm,Java,Hibernate,Grails,Gorm,我有以下两个域: User { UserData userData } UserData { static belongsTo = [user: User] } 在某个时刻,我想把两个用户合并成一个。我的意思是删除一个用户实例并将userData附加到另一个用户 我试过: User zombieUser User liveUser UserData data = zombieUser.userData zombieUser.delete() liveUser.userData

我有以下两个域:

User {
   UserData userData
}

UserData {
   static belongsTo = [user: User]
}
在某个时刻,我想把两个用户合并成一个。我的意思是删除一个用户实例并将userData附加到另一个用户

我试过:

User zombieUser
User liveUser

UserData data = zombieUser.userData
zombieUser.delete()
liveUser.userData = data
userData.user = liveUser
userData.save()
liveUser.save()
事实上,我尝试过不同的变体,不同的顺序,似乎所有可能的方式。但它总是失败,只有一个例外。当前代码将在以下情况下失败:

deleted object would be re-saved by cascade (remove deleted object from associations): [UserData#1]
如果我把
zombie.delete()
放在底部,在
*.save()
之后,我会得到:

Field error in object 'User' on field 'userData': rejected value [UserData : 1]; codes ... default message [Property [{0}] of class [{1}] with value [{2}] must be unique]
有没有办法将现有对象从一个对象重新连接到另一个对象


工作代码:

UserData userData = zombieUser.userData

userData.user = null
zombieUser.userData = null
zombieUser.save(flush: true)
userData.save()

liveUser.userData = userData
userData.user = liveUser
liveUser.save()
userDate.save(flush: true)

您需要向域类添加映射,以告诉它在删除对象时要做什么。例如,删除父项是否也应删除其所有子项

static mapping = {
    userData cascade: "all-delete-orphan"
}

您需要向域类添加映射,以告诉它在删除对象时要做什么。例如,删除父项是否也应删除其所有子项

static mapping = {
    userData cascade: "all-delete-orphan"
}

问题在于,由于您的
belongsTo
声明,并且根据,
userData
在删除
zombieUser
后立即从数据库中删除。调用
liveUser.save()
时,将再次保存
userData
。顺便说一下,您不需要再次调用
userData.save()
,因为这是
belongsTo
声明,
liveUser.save()
被级联到
userData

我看到了两个解决问题的选项:

  • 对新的
    userData
    对象执行
    userData
    的深度复制,并将此对象附加到
    liveUser
    ,如下所示:

    withTransaction {
      UserData data = new UserData(prop: zombieUser.userData.prop)
      liveUser.userData = data
      zombiUser.delete()
      liveUser.save()
    }
    
    删除
    zombieUser
    时,将级联删除旧的UserData对象,保存
    liveUser
    时,将创建一个新的UserData对象

  • userData
    中删除
    belongsTo
    您将不再受益于级联,您必须自己管理保存
    userData
    ,并确保在没有
    user
    引用它时从数据库中删除
    user.userData
    (当您在方法中多次调用
    save
    delete
    时,不要忘记为此进行事务处理)

  • 选择哪种方法取决于对象的耦合程度。通常情况下,如果对象非常耦合,您将受益于级联(通过
    belongsTo
    )并可能选择1。如果对象不是非常耦合,(即可能有多个用户具有相同的用户数据),则
    belongsTo
    是错误的,您应该选择方法2


    如果您有一个具有复杂依赖关系的GORM模型,中介绍的概念将对您有很大帮助。

    问题在于,由于您的
    属于
    声明,并且根据,一旦删除
    僵尸用户
    ,就会从数据库中删除
    用户数据。
    liveUser.save()调用
    时,
    userData
    将再次保存。顺便说一下,您不需要再次调用
    userData.save()
    ,因为此
    属于
    声明,
    liveUser.save()
    将级联到
    userData

    我看到了两个解决问题的选项:

  • 对新的
    userData
    对象执行
    userData
    的深度复制,并将此对象附加到
    liveUser
    ,如下所示:

    withTransaction {
      UserData data = new UserData(prop: zombieUser.userData.prop)
      liveUser.userData = data
      zombiUser.delete()
      liveUser.save()
    }
    
    删除
    zombieUser
    时,将级联删除旧的UserData对象,保存
    liveUser
    时,将创建一个新的UserData对象

  • userData
    中删除
    belongsTo
    您将不再受益于级联,您必须自己管理保存
    userData
    ,并确保在没有
    user
    引用它时从数据库中删除
    user.userData
    (当您在方法中多次调用
    save
    delete
    时,不要忘记为此进行事务处理)

  • 选择哪种方法取决于对象的耦合程度。通常情况下,如果对象非常耦合,您将受益于级联(通过
    belongsTo
    )并可能选择1。如果对象不是非常耦合,(即可能有多个用户具有相同的用户数据),则
    belongsTo
    是错误的,您应该选择方法2


    如果您有一个具有复杂依赖关系的GORM模型,中介绍的概念将对您大有帮助。

    hm,但是如果不需要删除子对象(UserData)?仅父对象(用户)。并将现有子对象附加到另一父对象。是否可能?hm,但是如果不需要删除子对象(UserData)?仅父对象(用户)怎么办。并将现有子项附加到另一个父项。是否可能?谢谢!在您的回答之后,我找到了第三个选项:在删除僵尸用户之前,将
    userData.user
    zombie.userData
    设置为
    null
    。谢谢!在您的回答之后,我找到了第三个选项:将
    userData.user
    zombie.userData
    设置为null