Reputation: 1334
I have two objects that have a one-to-one and one-to-many relationship.
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]
}
Basically, I have a GroupMember
who owns an InvitationCode
and can use another InvitationCode
. Or, an InvitationCode
can only belong-to/be-created-by one GroupMember
, but can be used/referenced by many GroupMember
's
The tables look like they're set up correctly - Both tables have fields for the other:
INVITATION_CODE.CREATOR_ID
and GROUP_MEMBER.INVITATION_CODE_ID
.
However, when I create a new InvitationCode
it seems the GroupMember
object is being updated and the invitationCodeId
is being set to the newly created 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??
I never set the creator.invitationCode
so I'm not sure how/why GORM is setting it. I'm also not sure where my mistake is in defining the domain. When I remove the flush: true
's I get a foreign-key restraint violation on GroupMember.invitationCode
.
Upvotes: 0
Views: 290
Reputation: 1880
The problem with your current setup is that the InvitationCode
domain has 2 references to the GroupMember
domain and grails has incorrectly inferred (in your case) that:
invitationCode
and creator
have a bidirectional association with each othermembers
is a unidirectional association to the GroupMember
classBut in reality, you want:
creator
to be a unidirectional association to the GroupMember
classmembers
to be a many-to-one relationship to the back-reference invitationCode
, making it a bidirectional associationUnderstandably, grails has a problem 'guessing' how to form this complex relationship.
The key is going to be the use of the mappedBy
property. I've used it successfully in mapping 2 many-to-many relationships on the same 2 classes, but not one like you need. I think what you need would be to have this in your InvitationCode
class:
static mappedBy = [
members: 'invitationCode',
creator: 'none' // because the relationship is unidirectional
]
Hopefully this works for you!
Upvotes: 1