有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Grails替换onetoone关联中的对象

我有以下两个领域:

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)

共 (2) 个答案

  1. # 1 楼答案

    问题是,由于belongsTo声明,并且根据cascading rules,一旦zombieUser被删除,就会从数据库中删除userData。当调用liveUser.save()时,将再次保存userData。顺便说一句,您不需要再次调用userData.save(),因为这个belongsTo声明,liveUser.save()被级联到userData

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

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

      withTransaction {
        UserData data = new UserData(prop: zombieUser.userData.prop)
        liveUser.userData = data
        zombiUser.delete()
        liveUser.save()
      }
      

      删除zombieUser时,旧的UserData对象将被级联删除,保存liveUser时,将创建一个新的UserData对象

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

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

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

  2. # 2 楼答案

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

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