I'm experiencing strange exceptions with my JPA-based table-per-class-hierarchy implementation.
My classes are defined similar to the following:
Code:
@Entity
@Table(name = "animal")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.CHAR)
@DiscriminatorValue("X") // There is no type "X", only "D" (dog) and "C" (cat), but JPA wants a value here
public class Animal implements Serializable {
// various getters and setters with simple mappings
}
@Entity
@DiscriminatorValue("D")
public class Dog extends Animal {
private Dog mother;
@ManyToOne
@JoinColumn(name = "motherId")
public Dog getMother() {
return mother;
}
}
@Entity
@DiscriminatorValue("C")
public class Cat extends Animal {
private Cat mother;
@ManyToOne
@JoinColumn(name = "motherId")
public Cat getMother() {
return mother;
}
}
@Entity
@Table(name = "kennel")
public class Kennel implements Serializable {
// various getters and setters with simple mappings
private List<Animal> animals;
@ManyToMany
@JoinTable(name = "kennelAnimal", joinColumns = @JoinColumn(name = "kennelId"), inverseJoinColumns = @JoinColumn(name = "animalId"))
@OrderColumn(name = "sequence", nullable = false, insertable = true, updatable = true)
public List<Animal> getAnimals() {
return animals;
}
}
A Dog can only have another Dog as a mother, and a Cat can only have another Cat as a mother, although the mother attribute can be null. Both Dogs and Cats can be in the same Kennel, and any Dog or Cat can be in more than one Kennel (sounds strange, I know, but just work with it).
The problem appears when I retrieve a Kennel and call its getAnimals() method. I get an error like the following:
Code:
2011-11-29 14:15:06,110 ERROR [org.hibernate.property.BasicPropertyAccessor] IllegalArgumentException in class: com.example.Cat, setter method of property: mother
2011-11-29 14:15:06,110 ERROR [org.hibernate.property.BasicPropertyAccessor] expected type: com.example.Cat, actual value: com.example.Dog
Exception in thread "main" org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of com.example.Cat.mother
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:128)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValues(AbstractEntityTuplizer.java:583)
at org.hibernate.tuple.entity.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:229)
at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:3847)
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:152)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:982)
at org.hibernate.loader.Loader.doQuery(Loader.java:857)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
at org.hibernate.loader.Loader.loadCollection(Loader.java:2166)
at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:62)
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:627)
at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:83)
at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1863)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:369)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111)
at org.hibernate.collection.PersistentList.iterator(PersistentList.java:138)
at com.example.Test.main(Test.java:34)
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:66)
... 16 more
Hibernate thinks that a Cat instance has a Dog instance for a mother, which it absolutely does not. The data is fine, but Hibernate is getting confused about types.
Any ideas what would cause this?