HHH-5191: Applying patch by Hernan Chanfreau

CollectionMetadataGenerator failed to obtain mappedBy attribute when is defined on superclasses

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@19371 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Adam Warski 2010-05-05 10:06:47 +00:00
parent 23db0f4de0
commit 19a1656446
14 changed files with 666 additions and 11 deletions

View File

@ -80,6 +80,7 @@ import org.slf4j.LoggerFactory;
/**
* Generates metadata for a collection-valued property.
* @author Adam Warski (adam at warski dot org)
* @author Hern<EFBFBD>n Chanfreau
*/
public final class CollectionMetadataGenerator {
private static final Logger log = LoggerFactory.getLogger(CollectionMetadataGenerator.class);
@ -533,7 +534,6 @@ public final class CollectionMetadataGenerator {
return middleEntityXmlId;
}
@SuppressWarnings({"unchecked"})
private String getMappedBy(Collection collectionValue) {
PersistentClass referencedClass = ((OneToMany) collectionValue.getElement()).getAssociatedClass();
@ -543,8 +543,31 @@ public final class CollectionMetadataGenerator {
return auditMappedBy;
}
Iterator<Property> assocClassProps = referencedClass.getPropertyIterator();
// searching in referenced class
String mappedBy = this.searchMappedBy(referencedClass, collectionValue);
if(mappedBy == null) {
log.debug("Going to search the mapped by attribute for " + propertyName + " in superclasses of entity: " + referencedClass.getClassName());
PersistentClass tempClass = referencedClass;
while ((mappedBy == null) && (tempClass.getSuperclass() != null)) {
log.debug("Searching in superclass: " + tempClass.getSuperclass().getClassName());
mappedBy = this.searchMappedBy(tempClass.getSuperclass(), collectionValue);
tempClass = tempClass.getSuperclass();
}
}
if(mappedBy == null) {
throw new MappingException("Unable to read the mapped by attribute for " + propertyName + " in "
+ referencedClass.getClassName() + "!");
}
return mappedBy;
}
@SuppressWarnings({"unchecked"})
private String searchMappedBy(PersistentClass referencedClass, Collection collectionValue) {
Iterator<Property> assocClassProps = referencedClass.getPropertyIterator();
while (assocClassProps.hasNext()) {
Property property = assocClassProps.next();
@ -552,13 +575,10 @@ public final class CollectionMetadataGenerator {
collectionValue.getKey().getColumnIterator())) {
return property.getName();
}
}
throw new MappingException("Unable to read the mapped by attribute for " + propertyName + " in "
+ referencingEntityName + "!");
}
return null;
}
@SuppressWarnings({"unchecked"})
private String getMappedBy(Table collectionTable, PersistentClass referencedClass) {
// If there's an @AuditMappedBy specified, returning it directly.
String auditMappedBy = propertyAuditingData.getAuditMappedBy();
@ -566,6 +586,31 @@ public final class CollectionMetadataGenerator {
return auditMappedBy;
}
// searching in referenced class
String mappedBy = this.searchMappedBy(referencedClass, collectionTable);
// not found on referenced class, searching on superclasses
if(mappedBy == null) {
log.debug("Going to search the mapped by attribute for " + propertyName + " in superclases of entity: " + referencedClass.getClassName());
PersistentClass tempClass = referencedClass;
while ((mappedBy == null) && (tempClass.getSuperclass() != null)) {
log.debug("Searching in superclass: " + tempClass.getSuperclass().getClassName());
mappedBy = this.searchMappedBy(tempClass.getSuperclass(), collectionTable);
tempClass = tempClass.getSuperclass();
}
}
if(mappedBy == null) {
throw new MappingException("Unable to read the mapped by attribute for " + propertyName + " in "
+ referencedClass.getClassName() + "!");
}
return mappedBy;
}
@SuppressWarnings({"unchecked"})
private String searchMappedBy(PersistentClass referencedClass, Table collectionTable) {
Iterator<Property> properties = referencedClass.getPropertyIterator();
while (properties.hasNext()) {
Property property = properties.next();
@ -576,9 +621,8 @@ public final class CollectionMetadataGenerator {
return property.getName();
}
}
}
throw new MappingException("Unable to read the mapped by attribute for " + propertyName + " in "
+ referencingEntityName + "!");
}
return null;
}
}

View File

@ -0,0 +1,26 @@
package org.hibernate.envers.test.integration.manytomany.inverseToSuperclass;
/**
* @author Hern<EFBFBD>n Chanfreau
*
*/
import org.hibernate.envers.Audited;
@Audited
public class DetailSubclass extends DetailSuperclass {
private String str2;
public DetailSubclass() {
}
public String getStr2() {
return str2;
}
public void setStr2(String str2) {
this.str2 = str2;
}
}

View File

@ -0,0 +1,26 @@
package org.hibernate.envers.test.integration.manytomany.inverseToSuperclass;
/**
* @author Hern<EFBFBD>n Chanfreau
*
*/
import org.hibernate.envers.Audited;
@Audited
public class DetailSubclass2 extends DetailSubclass {
private String str3;
public DetailSubclass2() {
}
public String getStr3() {
return str3;
}
public void setStr3(String str3) {
this.str3 = str3;
}
}

View File

@ -0,0 +1,38 @@
package org.hibernate.envers.test.integration.manytomany.inverseToSuperclass;
/**
* @author Hern<EFBFBD>n Chanfreau
*
*/
import java.util.List;
import org.hibernate.envers.Audited;
@Audited
public class DetailSuperclass {
private long id;
private List<Master> masters;
public DetailSuperclass() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public List<Master> getMasters() {
return masters;
}
public void setMasters(List<Master> masters) {
this.masters = masters;
}
}

View File

@ -0,0 +1,114 @@
package org.hibernate.envers.test.integration.manytomany.inverseToSuperclass;
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import javax.persistence.EntityManager;
import org.hibernate.ejb.Ejb3Configuration;
import org.hibernate.envers.test.AbstractEntityTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
* @author Hern<EFBFBD>n Chanfreau
*
*/
public class ManyToManyInverseToSuperclassTest extends AbstractEntityTest {
private long m1_id;
public void configure(Ejb3Configuration cfg) {
try {
URL url = Thread.currentThread().getContextClassLoader()
.getResource(
"mappings/manyToMany/inverseToSuperclass/mappings.hbm.xml");
cfg.addFile(new File(url.toURI()));
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
@BeforeClass(dependsOnMethods = "init")
public void initData() {
EntityManager em = getEntityManager();
Master m1 = new Master();
DetailSubclass det1 = new DetailSubclass2();
// Revision 1
em.getTransaction().begin();
det1.setStr2("detail 1");
m1.setStr("master");
m1.setItems(new ArrayList<DetailSubclass>());
m1.getItems().add(det1);
det1.setMasters(new ArrayList<Master>());
det1.getMasters().add(m1);
em.persist(m1);
em.getTransaction().commit();
m1_id = m1.getId();
// Revision 2
// em.getTransaction().begin();
//
// m1 = em.find(Master.class, m1_id);
//
// det2.setStr2("detail 2");
// det2.setParent(m1);
// m1.getItems().add(det2);
// em.getTransaction().commit();
//
// // Revision 3
// em.getTransaction().begin();
//
// m1 = em.find(Master.class, m1_id);
// m1.setStr("new master");
//
// det1 = m1.getItems().get(0);
// det1.setStr2("new detail");
// DetailSubclass det3 = new DetailSubclass2();
// det3.setStr2("detail 3");
// det3.setParent(m1);
//
// m1.getItems().get(1).setParent(null);
// // m1.getItems().remove(1);
// m1.getItems().add(det3);
//
// em.persist(m1);
// em.getTransaction().commit();
//
// // Revision 4
// em.getTransaction().begin();
//
// m1 = em.find(Master.class, m1_id);
//
// det1 = m1.getItems().get(0);
// det1.setParent(null);
// // m1.getItems().remove(det1);
//
// em.persist(m1);
// em.getTransaction().commit();
}
@Test
public void testHistoryExists() {
Master rev1_1 = getAuditReader().find(Master.class, m1_id, 1);
Master rev1_2 = getAuditReader().find(Master.class, m1_id, 2);
Master rev1_3 = getAuditReader().find(Master.class, m1_id, 3);
Master rev1_4 = getAuditReader().find(Master.class, m1_id, 4);
assert (rev1_1 != null);
assert (rev1_2 != null);
assert (rev1_3 != null);
assert (rev1_4 != null);
}
}

View File

@ -0,0 +1,48 @@
package org.hibernate.envers.test.integration.manytomany.inverseToSuperclass;
/**
* @author Hern<EFBFBD>n Chanfreau
*
*/
import java.util.List;
import org.hibernate.envers.Audited;
@Audited
public class Master {
private long id;
private String str;
private List<DetailSubclass> items;
public Master() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public List<DetailSubclass> getItems() {
return items;
}
public void setItems(List<DetailSubclass> items) {
this.items = items;
}
}

View File

@ -0,0 +1,26 @@
package org.hibernate.envers.test.integration.onetomany.inverseToSuperclass;
/**
* @author Hern<EFBFBD>n Chanfreau
*
*/
import org.hibernate.envers.Audited;
@Audited
public class DetailSubclass extends DetailSuperclass {
private String str2;
public DetailSubclass() {
}
public String getStr2() {
return str2;
}
public void setStr2(String str2) {
this.str2 = str2;
}
}

View File

@ -0,0 +1,26 @@
package org.hibernate.envers.test.integration.onetomany.inverseToSuperclass;
/**
* @author Hern<EFBFBD>n Chanfreau
*
*/
import org.hibernate.envers.Audited;
@Audited
public class DetailSubclass2 extends DetailSubclass {
private String str3;
public DetailSubclass2() {
}
public String getStr3() {
return str3;
}
public void setStr3(String str3) {
this.str3 = str3;
}
}

View File

@ -0,0 +1,36 @@
package org.hibernate.envers.test.integration.onetomany.inverseToSuperclass;
/**
* @author Hern<EFBFBD>n Chanfreau
*
*/
import org.hibernate.envers.Audited;
@Audited
public class DetailSuperclass {
private long id;
private Master parent;
public DetailSuperclass() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Master getParent() {
return parent;
}
public void setParent(Master parent) {
this.parent = parent;
}
}

View File

@ -0,0 +1,48 @@
package org.hibernate.envers.test.integration.onetomany.inverseToSuperclass;
/**
* @author Hern<EFBFBD>n Chanfreau
*
*/
import java.util.List;
import org.hibernate.envers.Audited;
@Audited
public class Master {
private long id;
private String str;
private List<DetailSubclass> items;
public Master() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public List<DetailSubclass> getItems() {
return items;
}
public void setItems(List<DetailSubclass> items) {
this.items = items;
}
}

View File

@ -0,0 +1,113 @@
package org.hibernate.envers.test.integration.onetomany.inverseToSuperclass;
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import javax.persistence.EntityManager;
import org.hibernate.ejb.Ejb3Configuration;
import org.hibernate.envers.test.AbstractEntityTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
* @author Hern<EFBFBD>n Chanfreau
*
*/
public class OneToManyInverseToSuperclassTest extends AbstractEntityTest {
private long m1_id;
public void configure(Ejb3Configuration cfg) {
try {
URL url = Thread.currentThread().getContextClassLoader()
.getResource(
"mappings/oneToMany/inverseToSuperclass/mappings.hbm.xml");
cfg.addFile(new File(url.toURI()));
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
@BeforeClass(dependsOnMethods = "init")
public void initData() {
EntityManager em = getEntityManager();
Master m1 = new Master();
DetailSubclass det1 = new DetailSubclass2();
DetailSubclass det2 = new DetailSubclass2();
// Revision 1
em.getTransaction().begin();
det1.setStr2("detail 1");
m1.setStr("master");
m1.setItems(new ArrayList<DetailSubclass>());
m1.getItems().add(det1);
det1.setParent(m1);
em.persist(m1);
em.getTransaction().commit();
m1_id = m1.getId();
// Revision 2
em.getTransaction().begin();
m1 = em.find(Master.class, m1_id);
det2.setStr2("detail 2");
det2.setParent(m1);
m1.getItems().add(det2);
em.getTransaction().commit();
// Revision 3
em.getTransaction().begin();
m1 = em.find(Master.class, m1_id);
m1.setStr("new master");
det1 = m1.getItems().get(0);
det1.setStr2("new detail");
DetailSubclass det3 = new DetailSubclass2();
det3.setStr2("detail 3");
det3.setParent(m1);
m1.getItems().get(1).setParent(null);
// m1.getItems().remove(1);
m1.getItems().add(det3);
em.persist(m1);
em.getTransaction().commit();
// Revision 4
em.getTransaction().begin();
m1 = em.find(Master.class, m1_id);
det1 = m1.getItems().get(0);
det1.setParent(null);
// m1.getItems().remove(det1);
em.persist(m1);
em.getTransaction().commit();
}
@Test
public void testHistoryExists() {
Master rev1_1 = getAuditReader().find(Master.class, m1_id, 1);
Master rev1_2 = getAuditReader().find(Master.class, m1_id, 2);
Master rev1_3 = getAuditReader().find(Master.class, m1_id, 3);
Master rev1_4 = getAuditReader().find(Master.class, m1_id, 4);
assert (rev1_1 != null);
assert (rev1_2 != null);
assert (rev1_3 != null);
assert (rev1_4 != null);
}
}

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="WINDOWS-1251"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class
name="org.hibernate.envers.test.integration.manytomany.inverseToSuperclass.Master"
table="HIB_MASTER_ENTITY">
<id name="id" column="ID" type="long">
<generator class="increment" />
</id>
<property name="str" column="STR" />
<bag name="items" lazy="true" cascade="all" access="property" inverse="true"
table="HIB_MASTER_DETAIL">
<key column="ID_MASTER" />
<many-to-many
class="org.hibernate.envers.test.integration.manytomany.inverseToSuperclass.DetailSubclass2"
column="ID_DETAIL" />
</bag>
</class>
<class
name="org.hibernate.envers.test.integration.manytomany.inverseToSuperclass.DetailSuperclass"
table="HIB_DETAIL_ENTITY" abstract="true">
<id name="id" column="ID" type="long">
<generator class="increment" />
</id>
<discriminator column="DISCRIMINATOR" type="string" />
<bag name="masters" lazy="true" access="property" table="HIB_MASTER_DETAIL">
<key column="ID_DETAIL" />
<many-to-many
class="org.hibernate.envers.test.integration.manytomany.inverseToSuperclass.Master"
column="ID_MASTER" />
</bag>
<subclass
name="org.hibernate.envers.test.integration.manytomany.inverseToSuperclass.DetailSubclass"
discriminator-value="SUB">
<property name="str2" column="STR2" />
<subclass
name="org.hibernate.envers.test.integration.manytomany.inverseToSuperclass.DetailSubclass2"
discriminator-value="SUB2"
extends="org.hibernate.envers.test.integration.manytomany.inverseToSuperclass.DetailSubclass">
<property name="str3" column="STR3" />
</subclass>
</subclass>
</class>
</hibernate-mapping>

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="WINDOWS-1251"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class
name="org.hibernate.envers.test.integration.onetomany.inverseToSuperclass.Master"
table="HIB_MASTER_ENTITY">
<id name="id" column="ID" type="long">
<generator class="increment" />
</id>
<property name="str" column="STR" />
<bag name="items" lazy="true" cascade="all" access="property"
inverse="true">
<key column="ID_MASTER" />
<one-to-many
class="org.hibernate.envers.test.integration.onetomany.inverseToSuperclass.DetailSubclass2" />
</bag>
</class>
<class
name="org.hibernate.envers.test.integration.onetomany.inverseToSuperclass.DetailSuperclass"
table="HIB_DETAIL_ENTITY" abstract="true">
<id name="id" column="ID" type="long">
<generator class="increment" />
</id>
<discriminator column="DISCRIMINATOR" type="string" />
<many-to-one name="parent" column="ID_MASTER"
class="org.hibernate.envers.test.integration.onetomany.inverseToSuperclass.Master" />
<subclass
name="org.hibernate.envers.test.integration.onetomany.inverseToSuperclass.DetailSubclass"
discriminator-value="SUB">
<property name="str2" column="STR2" />
<subclass
name="org.hibernate.envers.test.integration.onetomany.inverseToSuperclass.DetailSubclass2"
discriminator-value="SUB2" extends="org.hibernate.envers.test.integration.onetomany.inverseToSuperclass.DetailSubclass">
<property name="str3" column="STR3" />
</subclass>
</subclass>
</class>
</hibernate-mapping>

View File

@ -43,6 +43,7 @@
<package name="org.hibernate.envers.test.integration.interfaces.hbm.propertiesAudited2.union" />
<package name="org.hibernate.envers.test.integration.manytomany" />
<package name="org.hibernate.envers.test.integration.manytomany.biowned" />
<package name="org.hibernate.envers.test.integration.manytomany.inverseToSuperclass" />
<package name="org.hibernate.envers.test.integration.manytomany.sametable" />
<package name="org.hibernate.envers.test.integration.manytomany.ternary" />
<package name="org.hibernate.envers.test.integration.manytomany.unidirectional" />
@ -53,6 +54,7 @@
<package name="org.hibernate.envers.test.integration.notinsertable.manytoone" />
<package name="org.hibernate.envers.test.integration.onetomany" />
<package name="org.hibernate.envers.test.integration.onetomany.detached" />
<package name="org.hibernate.envers.test.integration.onetomany.inverseToSuperclass" />
<package name="org.hibernate.envers.test.integration.onetoone.bidirectional" />
<package name="org.hibernate.envers.test.integration.onetoone.bidirectional.ids" />
<package name="org.hibernate.envers.test.integration.onetoone.unidirectional" />