I have come accross something that at first view seems to be a bug in Gorm (grails 1.3.7). I thought I’d post the problem here before going for the jira issue, in case I’m getting it wrong.
Here’s the issue:
I have one domain class, it refers to a parent object of the same class, and also can have a pointer to an alias, also of the same domain class.
This is the domain class:
class Mydomain {
String name
Mydomain alias
Mydomain parent
Mydomain foo
static constraints = {
parent(nullable: true)
alias(nullable: true)
foo(nullable: true)
}
}
If I execute the following script:
Mydomain.list()*.delete()
def one=new Mydomain(name:'one').save()
new Mydomain(name:'two', parent:one).save()
Mydomain.list().each{
println it.name
println "parent:${it.parent?.name}"
println "alias:${it.alias?.name}"
println "foo:${it.foo?.name}"
println "============================"
}
I get the following result:
one
parent:null
alias:two
foo:null
============================
two
parent:one
alias:null
foo:null
============================
This means that when I set two.parent=one, gorm goes and sets one.alias=two.
I guess that gorm does this because it infers that there is a bidirectional relationship between one and two, and then sets the first property of class Mydomain of object one to the reference of two.
I can see this sort of behaviour working with bidirectional relationships between Author and Book (assuming that an author only writes one book of course), but in my case this is dangerous, becaus gorm goes and overwrites a relationship that has nothing to do with this.
So my question would be, how do I tell GORM to treat this as unidirectional nullable relationships?
Thanks for any ideas
Update: Business case
This is the business case that I am trying to model.
A company has a name, and can have subsidiaries, warehouses, local offices, etc. This is modeled with the help of the parent relationship, effectively creating a tree of Companies:
class Company {
String name
Company parent
}
Now, the representation of this organizational structure is not the same for everyone, some people may not care about the office level, or event the group level. This is why a company can have an alias in a parallel representation. It is still the same company, can have a different name, but you would like to be able to navigate between these parallel tree organizations via the alias relationship.
class Company {
String name
Company parent
Company alias
}
So yes, there are multiple relationships to self, but they have very distinct meanings, and I understand that GORM uses the most frequent simple case as a default, but I am really trying everything I can in the DSL to instruct GORM to do the right thing, but unsuccessfully.
The conventional way of doing this would be to add a bidirectional one-to-many relationship, with a mappedBy directive:
class Company {
String name
Company alias
static belongsTo=[parent:Company]
static hasMany=[children:Company]
static mappedBy=[children:'parent']
}
But in many GORM articles this idiom is discouraged, because of severe performance issues. That is why I want an unidirectional relationship
Company ---(parent)---> Company
After posting a JIRA issue
http://jira.grails.org/browse/GRAILS-9062?focusedCommentId=70641#comment-70641
and some exchanges in the mailing list,
http://markmail.org/message/xcmcclr2lv7ecrbn
The solution was suggested by Graeme Rocher.
Just add the following mappedBy closure
This will instruct GORM not to make the assumption that a bidirectional relationship is needed.
Thanks to all for your expert help!