Hi
I am having trouble mapping the single table inheritance with annotations. I have pasted the code below and it shows the version with annotations and the xml mapping file. For the test I am explicitly using an AnnotationConfiguration() and a classic Configuration() so I can exercise the mapping and the annotations. When I use the mapping file with the model below it works just fine but when I use the annotations it breaks. I would like to use the annotations because I would like to use JPA and when I substitute Toplink for Hibernate it works just fine so this must be down to Hibernates implementation details.
Hibernate version:
Hibernate 3.2.5
Mapping documents:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping
package="entity.test"
default-access="property">
<class name="Person" abstract="true" proxy="Person">
<id name="id">
<generator class="increment"/>
</id>
<discriminator
type="string"
column="type" />
<property name="name"
not-null="true"/>
<many-to-one name="parent"/>
<set name="children" inverse="true">
<key column="parent"/>
<one-to-many class="Parent"/>
</set>
<subclass name="Parent"
discriminator-value="PARENT" proxy="Parent">
<property name="job"/>
</subclass>
<subclass name="Child"
discriminator-value="CHILD" proxy="Child">
</subclass>
</class>
<class name="Car">
<id name="id">
<generator class="increment"/>
</id>
<property name="colour"
not-null="true"/>
<property name="make"
not-null="true"/>
<many-to-one name="owner"
lazy="false"/>
</class>
</hibernate-mapping>
@Entity
@MappedSuperclass
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING)
@org.hibernate.annotations.ForceDiscriminator
@Table(name = "PERSON")
public abstract class Person {
@Id
@GeneratedValue()
private Long id;
private String name;
@ManyToOne(cascade = {}, fetch = FetchType.LAZY)
private Person parent;
@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "parent")
private Set<Person> children = new HashSet<Person>(0);
protected Person() {}
// getters and setters....
}
@Entity
@DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING)
@DiscriminatorValue("PARENT")
@org.hibernate.annotations.ForceDiscriminator
@Table(name = "PERSON")
public class Parent extends Person {
private String job;
}
@Entity
@DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING)
@DiscriminatorValue("CHILD")
@org.hibernate.annotations.ForceDiscriminator
@Table(name = "PERSON")
public class Child extends Person {
}
@Entity
public class Car {
@Id
@GeneratedValue()
private Long id;
private String make;
private String colour;
@ManyToOne(cascade = {}, fetch = FetchType.LAZY)
private Person owner;
public Car() {}
}
Code between sessionFactory.openSession() and session.close():
session.beginTransaction();
//create parent
Parent parent = new Parent();
parent.setName("parent");
parent.setJob("fireman");
//create child
Child child = new Child();
child.setName("child");
//create car
Car car = new Car();
car.setColour("red");
car.setMake("honda");
//set up relationships
parent.getChildren().add(child);
child.setParent(parent);
car.setOwner(parent);
//persist all
session.persist(parent);
session.persist(child);
session.persist(car);
session.flush();
session.getTransaction().commit();
//clear so we have a clean slate for queries
session.clear();
session.beginTransaction();
// get some persons
List<Person> persons = session.createQuery("select p from Person p").list();
session.getTransaction().commit();
Full stack trace of any exception that occurs:
org.hibernate.jdbc.AbstractBatcher.log(AbstractBatcher.java:401) 2008-02-15 14:50:04,734 [main] DEBUG -
select
child0_.id as id0_,
child0_.name as name0_,
child0_.parent_id as parent5_0_
from
PERSON child0_
Hibernate:
select
child0_.id as id0_,
child0_.name as name0_,
child0_.parent_id as parent5_0_
from
PERSON child0_
org.hibernate.type.NullableType.nullSafeGet(NullableType.java:172) 2008-02-15 14:50:04,749 [main] DEBUG - returning '1' as column: id0_
org.hibernate.type.NullableType.nullSafeGet(NullableType.java:172) 2008-02-15 14:50:04,749 [main] DEBUG - returning 'parent' as column: name0_
org.hibernate.type.NullableType.nullSafeGet(NullableType.java:166) 2008-02-15 14:50:04,749 [main] DEBUG - returning null as column: parent5_0_
org.hibernate.type.NullableType.nullSafeGet(NullableType.java:172) 2008-02-15 14:50:04,765 [main] DEBUG - returning '2' as column: id0_
org.hibernate.type.NullableType.nullSafeGet(NullableType.java:172) 2008-02-15 14:50:04,765 [main] DEBUG - returning 'child' as column: name0_
org.hibernate.type.NullableType.nullSafeGet(NullableType.java:172) 2008-02-15 14:50:04,765 [main] DEBUG - returning '1' as column: parent5_0_
org.hibernate.jdbc.AbstractBatcher.log(AbstractBatcher.java:401) 2008-02-15 14:50:04,781 [main] DEBUG -
select
person0_.id as id0_,
person0_.name as name0_,
person0_.parent_id as parent5_0_
from
PERSON person0_
Hibernate:
select
person0_.id as id0_,
person0_.name as name0_,
person0_.parent_id as parent5_0_
from
PERSON person0_
org.hibernate.type.NullableType.nullSafeGet(NullableType.java:172) 2008-02-15 14:50:04,796 [main] DEBUG - returning '1' as column: id0_
Exception in thread "main" org.hibernate.InstantiationException: Cannot instantiate abstract class or interface: entity.test.Person
at org.hibernate.tuple.PojoInstantiator.instantiate(PojoInstantiator.java:78)
at org.hibernate.tuple.PojoInstantiator.instantiate(PojoInstantiator.java:100)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.instantiate(AbstractEntityTuplizer.java:351)
at org.hibernate.persister.entity.AbstractEntityPersister.instantiate(AbstractEntityPersister.java:3606)
at org.hibernate.impl.SessionImpl.instantiate(SessionImpl.java:1275)
at org.hibernate.impl.SessionImpl.instantiate(SessionImpl.java:1264)
at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1299)
at org.hibernate.loader.Loader.getRow(Loader.java:1206)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:580)
at org.hibernate.loader.Loader.doQuery(Loader.java:701)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
at org.hibernate.loader.Loader.doList(Loader.java:2220)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2104)
at org.hibernate.loader.Loader.list(Loader.java:2099)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:378)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:338)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:172)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1121)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
at entity.test.TestInheritance.runQueries(TestInheritance.java:145)
at entity.test.TestInheritance.runTests(TestInheritance.java:119)
at entity.test.TestInheritance.testAnnotationInheritance(TestInheritance.java:177)
at entity.test.TestInheritance.main(TestInheritance.java:191)
Name and version of the database you are using:
Oracle 10g
The generated SQL (show_sql=true):
select
child0_.id as id0_,
child0_.name as name0_,
child0_.parent_id as parent5_0_
from
PERSON child0_
select
person0_.id as id0_,
person0_.name as name0_,
person0_.parent_id as parent5_0_
from
PERSON person0_
Last edited by ericp on Fri Feb 15, 2008 12:43 pm, edited 1 time in total.
|