Please consider the following HBM-Mapping file:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="org.hibernate.test" default-access="field">
<class entity-name="TestWorkflowItem" name="WorkflowItem" table="test_workflowitem">
<id name="id" type="long">
<generator class="native"/>
</id>
<property name="name" column="name" not-null="true" type="string"/>
<many-to-one cascade="all" entity-name="TestWorkflowItem" class="WorkflowItem" column="next_id" name="next" unique="true" foreign-key="fk_testworkflowitem_workflowitem"/>
</class>
</hibernate-mapping>
... and the code of WorkflowItem:
Code:
package org.hibernate.test;
public final class WorkflowItem {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private WorkflowItem next;
public WorkflowItem() {
}
boolean hasNext() {
return next != null;
}
public void setNext(WorkflowItem newNext) {
next = newNext;
}
public WorkflowItem getNext() {
return next;
}
public String getName() {
return name;
}
public void setName(String newName) {
name = newName;
}
}
When building the metadata like in the ORMUnitTestCase for Hibernate 5 I get the following exception:
Code:
Caused by: org.hibernate.MappingException: An association from the table test_workflowitem refers to an unmapped class: org.hibernate.test.WorkflowItem
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.secondPassCompileForeignKeys(InFlightMetadataCollectorImpl.java:1803)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.secondPassCompileForeignKeys(InFlightMetadataCollectorImpl.java:1774)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1593)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:278)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.build(MetadataBuildingProcess.java:83)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:418)
...
Please note, the mapping for class WorkflowItem has an entity name set. The mapping for property 'next' in this class references class WorkflowItem also via this entity name. It seems that the foreign key handling in the metadata buildig process does not take this entity name into account, but uses the class name instead. Therefore it cannot find a mapping by class name.
(In reality/production there are different mappings for the WorkflowItem class with different entity-names. There is no default mapping without explicit entity-name.)
Hibernate 3.6.x and Hibernate 4.3.x do not have this problem.
Please confirm this bug.
If so, it would be great if this could be fixed for Hibernate 5.0.x.
I'm migrating from Hibernate 3.6 to Hibernate 5.0.10 and got stuck because of this problem.
For completeness here is the test code:
Code:
public class ORMUnitTestCase extends BaseCoreFunctionalTestCase {
// Add your entities here.
@Override
protected Class[] getAnnotatedClasses() {
return new Class[] {
// Foo.class,
// Bar.class
};
}
// If you use *.hbm.xml mappings, instead of annotations, add the mappings here.
@Override
protected String[] getMappings() {
return new String[] {
"TestWorkflowItem.hbm.xml"
};
}
// If those mappings reside somewhere other than resources/org/hibernate/test, change this.
@Override
protected String getBaseForMappings() {
return "org/hibernate/test/";
}
// Add in any settings that are specific to your test. See resources/hibernate.properties for the defaults.
@Override
protected void configure(Configuration configuration) {
super.configure( configuration );
configuration.setProperty( AvailableSettings.SHOW_SQL, Boolean.TRUE.toString() );
configuration.setProperty( AvailableSettings.FORMAT_SQL, Boolean.TRUE.toString() );
//configuration.setProperty( AvailableSettings.GENERATE_STATISTICS, "true" );
}
// Add your tests, using standard JUnit.
@Test
public void hhh123Test() throws Exception {
// BaseCoreFunctionalTestCase automatically creates the SessionFactory and provides the Session.
Session s = openSession();
Transaction tx = s.beginTransaction();
// Do stuff...
WorkflowItem first = new WorkflowItem();
first.setName("First");
WorkflowItem second = new WorkflowItem();
second.setName("Second");
first.setNext(second);
s.save("TestWorkflowItem", first);
List list = s.createQuery("from TestWorkflowItem where name = 'First'").list();
assertEquals(1, list.size());
WorkflowItem loaded = (WorkflowItem) list.get(0);
assertNotNull(loaded.getNext());
assertEquals("Second", loaded.getNext().getName());
System.out.println("DONE");
tx.commit();
s.close();
}
}
Thanks for your help,
Holger