hibernate 4.3
I have mixed mapping configuration - with annotations and hbm.xml files.
According to documentation
http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/ch10.html
Quote:
You must specify an extends attribute in the subclass mapping, naming a previously mapped superclass. Previously this feature made the ordering of the mapping documents important. Since Hibernate, the ordering of mapping files is irrelevant when using the extends keyword.
And here is the problem - if class Z, mapped with annotation, has a foreing key to class B, mapped with xml, and this class B is a sublcass of A - it is important, that A was added to Configuration before B.
If all three classes are mapped with xml - order isn't important.
Is it a bug? Or is it a known behavior with "Won't Fix" resolution?
Here is the test:
mixedConfigurationWithReverseOrder is failed with
Quote:
org.hibernate.AnnotationException: @OneToOne or @ManyToOne on me.popandopolos.annotation.Z.b references an unknown entity: me.popandopolos.annotation.B
Code:
package me.popandopolos.annotation;
import java.io.InputStream;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.testing.ServiceRegistryBuilder;
import org.junit.Test;
public class MixedConfigurationTest {
@Test
public void mixedConfigurationWithNormalOrder() {
Configuration cfg = buildConfiguration();
String[] xmlFiles = new String[] {
"me/popandopolos/annotation/A.hbm.xml", //
"me/popandopolos/annotation/B.hbm.xml", //
};
Class[] annotatedClasses = new Class[] { Z.class };
addMappings(cfg, xmlFiles, annotatedClasses);
cfg.buildSessionFactory(ServiceRegistryBuilder.buildServiceRegistry(cfg.getProperties()));
}
@Test
public void mixedConfigurationWithReverseOrder() {
Configuration cfg = buildConfiguration();
String[] xmlFiles = new String[] {
"me/popandopolos/annotation/B.hbm.xml", //
"me/popandopolos/annotation/A.hbm.xml", //
};
Class[] annotatedClasses = new Class[] { Z.class };
addMappings(cfg, xmlFiles, annotatedClasses);
cfg.buildSessionFactory(ServiceRegistryBuilder.buildServiceRegistry(cfg.getProperties()));
}
@Test
public void xmlConfigurationWithReverseOrder() {
Configuration cfg = buildConfiguration();
String[] xmlFiles = new String[] {
"me/popandopolos/annotation/Z.hbm.xml", //
"me/popandopolos/annotation/B.hbm.xml", //
"me/popandopolos/annotation/A.hbm.xml", //
};
addMappings(cfg, xmlFiles, new Class[] {});
cfg.buildSessionFactory(ServiceRegistryBuilder.buildServiceRegistry(cfg.getProperties()));
}
private void addMappings(Configuration configuration, String[] xmlFiles, Class[] annotatedClasses) {
if (annotatedClasses != null) {
for (Class<?> annotatedClass : annotatedClasses) {
configuration.addAnnotatedClass(annotatedClass);
}
}
if (xmlFiles != null) {
for (String xmlFile : xmlFiles) {
InputStream is = getClass().getClassLoader().getResourceAsStream(xmlFile);
configuration.addInputStream(is);
}
}
}
private Configuration buildConfiguration() {
Configuration configuration = new Configuration();
configuration.setProperty(Environment.USE_SECOND_LEVEL_CACHE, Boolean.FALSE.toString());
configuration.setProperty(Environment.HBM2DDL_AUTO, "create-drop");
configuration.setProperty(Environment.DIALECT, H2Dialect.class.getName());
return configuration;
}
}
And here classes and mappings:
Code:
package me.popandopolos.annotation;
public class A {
private Integer aId = 0;
public Integer getAId() {
return this.aId;
}
public void setAId(Integer aId) {
this.aId = aId;
}
}
Code:
package me.popandopolos.annotation;
public class B extends A {
private Integer bId = 0;
public B() {
super();
}
public Integer getBId() {
return bId;
}
public void setBId(Integer bId) {
this.bId = bId;
}
}
Code:
package me.popandopolos.annotation;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "Z")
public class Z {
private Integer zId = null;
private B b = null;
@Id
@GeneratedValue
@Column(name = "zID")
public Integer getZId() {
return zId;
}
public void setZId(Integer zId) {
this.zId = zId;
}
@ManyToOne(optional = false, targetEntity = B.class, fetch = FetchType.LAZY)
@JoinColumn(name = "bID", referencedColumnName = "bID")
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
}
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="me.popandopolos.annotation.A" table="A">
<id name="AId" column="aID" type="java.lang.Integer">
<generator class="identity"/>
</id>
</class>
</hibernate-mapping>
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<joined-subclass name="me.popandopolos.annotation.B" table="B"
extends="me.popandopolos.annotation.A">
<key column="aID"/>
<property name="BId" column="bID" type="java.lang.Integer"
not-null="true"/>
</joined-subclass>
</hibernate-mapping>
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="me.popandopolos.annotation.Z" table="Z">
<id name="ZId" column="zID" type="java.lang.Integer">
<generator class="identity"/>
</id>
<many-to-one
class="me.popandopolos.annotation.B"
column="bID"
name="B"
outer-join="false"/>
</class>
</hibernate-mapping>