Gorm一对一和一对多

Gorm one-to-one and one-to-many

我有两个具有一对一和一对多关系的对象。

class GroupMember {
   /**
    * InvitationCode used to join this Group
    */
   InvitationCode invitationCode

   static constraints = {
      // group creator member object won't have used an invitation code
      invitationCode(nullable: true) 
   }
}

class InvitationCode {
   /**
    * GroupMember who created the code, not used the code
    */
   GroupMember creator

   // I tried removing this, it has no effect.
   static hasMany = [members: GroupMember]
}

基本上,我有一个 GroupMember,他拥有一个 InvitationCode 并且可以使用另一个 InvitationCode。或者,一个InvitationCode只能belong-to/be-created-by一个GroupMember,但可以used/referenced多个GroupMember

这些表看起来设置正确 - 两个表都有另一个字段: INVITATION_CODE.CREATOR_IDGROUP_MEMBER.INVITATION_CODE_ID.

但是,当我创建一个新的 InvitationCode 时,GroupMember 对象似乎正在更新并且 invitationCodeId 被设置为新创建的 InvitationCode's id.

GroupMember creator = new GroupMember(
   invitationCode: null // group creator - didn't use an invitation code
)
creator.save(flush: true)

InvitationCode invitationCode = new InvitationCode(
   creator: creator
)
invitationCode.save(flush: true)

GroupMember _creatorMember = GroupMember.findById(creator.id)
assert _creatorMember.invitationCode == invitationCode // true??

我从未设置 creator.invitationCode 所以我不确定 how/why GORM 是否设置了它。我也不确定我在定义域时的错误在哪里。当我删除 flush: true 时,我在 GroupMember.invitationCode.

上遇到外键限制违规

您当前设置的问题是 InvitationCode 域有 2 个对 GroupMember 域的引用并且 grails 错误地推断(在您的情况下):

  • invitationCodecreator 相互之间存在双向关联
  • membersGroupMember class
  • 的单向关联

但实际上,你想要:

  • creatorGroupMember class
  • 的单向关联
  • members 与 back-reference invitationCode 的 many-to-one 关系,使其成为双向关联

可以理解,grails 有一个问题 'guessing' 如何形成这种复杂的关系。

关键是要使用mappedBy属性。我已经成功地使用它在相同的 2 class 上映射 2 many-to-many 关系,但不是您需要的那样。我 认为 你需要的是在你的 InvitationCode class:

static mappedBy = [
    members: 'invitationCode',
    creator: 'none' // because the relationship is unidirectional
]

希望这对你有用!