Skip to content

Commit 9941fae

Browse files
committed
fix for GRAILS-3273 "Many-To-Many Mapping with Subclasses does not work"
1 parent e5b76a2 commit 9941fae

File tree

2 files changed

+63
-5
lines changed

2 files changed

+63
-5
lines changed

src/java/org/codehaus/groovy/grails/commons/DefaultGrailsDomainClass.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public class DefaultGrailsDomainClass extends AbstractGrailsClass implements Gr
5252
private Map mappedBy;
5353
private Validator validator;
5454
private String mappingStrategy = GrailsDomainClass.GORM;
55-
private List owners = new ArrayList();
55+
private List<Class> owners = new ArrayList<Class>();
5656
private boolean root = true;
5757
private Set subClasses = new HashSet();
5858
private Collection embedded;
@@ -406,13 +406,16 @@ private void establishOwnerOfManyToMany(DefaultGrailsDomainClassProperty propert
406406
Object related = BeanUtils.instantiateClass(relatedClassType);
407407
Object relatedBelongsTo = GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(related, GrailsDomainClassProperty.BELONGS_TO);
408408
boolean owningSide = false;
409-
boolean relatedOwner = this.owners.contains(relatedClassType);
409+
boolean relatedOwner = isOwningSide(relatedClassType, this.owners);
410410
final Class propertyClass = property.getDomainClass().getClazz();
411411
if(relatedBelongsTo instanceof Collection) {
412-
owningSide = ((Collection)relatedBelongsTo).contains(propertyClass);
412+
final Collection associatedOwners = (Collection)relatedBelongsTo;
413+
owningSide = isOwningSide(propertyClass, associatedOwners);
413414
}
414-
else if (relatedBelongsTo != null) {
415-
owningSide = relatedBelongsTo.equals(propertyClass);
415+
else if (relatedBelongsTo instanceof Class) {
416+
final Collection associatedOwners = new ArrayList();
417+
associatedOwners.add(relatedBelongsTo);
418+
owningSide = isOwningSide(propertyClass, associatedOwners);
416419
}
417420
property.setOwningSide(owningSide);
418421
if(relatedOwner && property.isOwningSide()) {
@@ -422,6 +425,15 @@ else if(!relatedOwner && !property.isOwningSide() && !(property.isCircular() &&
422425
throw new GrailsDomainException("No owner defined between domain classes ["+propertyClass+"] and ["+relatedClassType+"] in a many-to-many relationship. Example: def belongsTo = "+relatedClassType.getName());
423426
}
424427
}
428+
private boolean isOwningSide(Class relatedClassType, Collection<Class> owners) {
429+
boolean relatedOwner = false;
430+
for (Class relatedClass : owners) {
431+
if(relatedClass.isAssignableFrom(relatedClassType)) {
432+
relatedOwner = true; break;
433+
}
434+
}
435+
return relatedOwner;
436+
}
425437

426438
/**
427439
* Establishes whether the relationship is a bi-directional or uni-directional one-to-many
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package org.codehaus.groovy.grails.orm.hibernate;
2+
3+
class ManyToManyWithInheritanceTests extends AbstractGrailsHibernateTests {
4+
5+
@Override
6+
protected void onSetUp() {
7+
gcl.parseClass '''
8+
import grails.persistence.*
9+
10+
@Entity
11+
class Pentagon extends Shape{
12+
13+
}
14+
@Entity
15+
class Shape {
16+
static hasMany = [attributes:ShapeAttribute]
17+
}
18+
@Entity
19+
class ShapeAttribute{
20+
21+
String name
22+
String value
23+
24+
static hasMany = [shapes: Shape]
25+
static belongsTo = Shape
26+
27+
}
28+
'''
29+
}
30+
31+
void testManyToManyMappingWithInheritance() {
32+
def Pentagon = ga.getDomainClass("Pentagon").clazz
33+
def ShapeAttribute = ga.getDomainClass("ShapeAttribute").clazz
34+
35+
def p = Pentagon.newInstance()
36+
p.addToAttributes(name:"sides", value:"5")
37+
38+
assert p.save(flush:true) : "should have saved instance"
39+
40+
session.clear()
41+
42+
p = Pentagon.get(1)
43+
44+
assert 1 == p.attributes.size() : "should have one attribute"
45+
}
46+
}

0 commit comments

Comments
 (0)