I'm facing a weird issue in grails (3.1.11) closely related to this blog post (from 2010 !): http://codedumpblog.blogspot.de/2010/02/grails-many-to-many-with-lists.html
I'm trying to model the following simple relations:
Organization
and Person
) that share a child type (Address
) in a hasMany
association. Address
can only belong to one of the parents, never to both simultaneously. Organization
or a Person
should delete all its Address
-es.So far I have the following code:
class Organization {
List addresses
static hasMany = [addresses: Address]
static mapping = {
addresses sort: 'country', order: 'asc', cascade: "all-delete-orphan"
}
}
class Person {
List addresses
static hasMany = [addresses: Address]
static mapping = {
addresses sort: 'country', order: 'asc', cascade: "all-delete-orphan"
}
}
class Address {
String country
//...truncated...
static belongsTo = [organization: Organization,
person : Person]
static constraints = {
organization nullable: true
person nullable: true
}
}
But after running this I get the following Hibernate exception:
org.hibernate.MappingException: Duplicate property mapping of _addressesIndexBackref found in com.example.Address
As in the blog post, the problem only shows up if the addresses
field has the same name in both parent classes. If I rename the fields to organizationAddresses
and personAddresses
respectively, then everything works as expected.
I'd like the field to remain as just addresses
though, so I don't have to call stuff like organization.organizationAddresses
and person.personAddresses
.
Is there a modern workaround for this almost 7 year old issue?
The Problem
This looks like a Hibernate Bug. Occurs when you create a Class
with two relationships connected by many-to-one
In your case, there are two classes related to Address
by hasMany
The Solution
Replace the membership
relationship by use
relationship. In your case, this is done like this:
Create a class ListAddresses
to hold the adresses of a Person
or Organization
:
class ListAddresses {
List addresses
static hasMany = [addresses: Address]
static mapping = {
addresses sort: 'country', order: 'asc', cascade: "all-delete-orphan"
}
}
Delete all relationships from Address
and create the new one:
class Address {
String country
//...truncated...
static belongsTo = [list:ListAddresses]
/*static belongsTo = [organization: Organization,
person : Person]*/
static constraints = {
/*organization nullable: true
person nullable: true*/
}
}
Use ListAddresses
in Person
or Organization
class Organization {
ListAddresses addresses
static mapping = {
addresses cascade: "all-delete-orphan"
}
}
class Person {
ListAddresses addresses
static mapping = {
addresses cascade: "all-delete-orphan"
}
}
This answer is based on the question. But in my case, the solution was easier because I replace the belongsTo
relationship and not hasMany
.