Entity Hierarchy: (All contained in the same package named 'test')
@Entity @Table(name="device") Class Device { int deviceId; User user; }
@Entity @Inheritance(strategy=InheritanceType.JOINED) @Table(name="adv_user") Class AdvancedUser extends User { }
@Entity @Inheritance(strategy=InheritanceType.JOINED) @DiscriminatorColumn(discriminatorType=DiscriminatorType.STRING, name="userId") @Table(name="user") Class User extends UserBase { }
@Entity @MappedSuperclass Class UserBase { String userId; }
Now I have a simple Test which persists a device (deviceId = 1) and a user (userId = testuser), afterwards I try to find the User with em.find(Device.class, 1)
This will throw me the following exception:
javax.persistence.PersistenceException: org.hibernate.WrongClassException: Object with id: testuser was not of the specified subclass: test.User (Discriminator: testuser) at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1387) at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:838) at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:781) ... Caused by: org.hibernate.WrongClassException: Object with id: testuser was not of the specified subclass: test.User (Discriminator: testuser) at org.hibernate.loader.Loader.getInstanceClass(Loader.java:1769) at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1586) at org.hibernate.loader.Loader.getRow(Loader.java:1509) at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:719) at org.hibernate.loader.Loader.processResultSet(Loader.java:949) at org.hibernate.loader.Loader.doQuery(Loader.java:917) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:348) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:318) at org.hibernate.loader.Loader.loadEntity(Loader.java:2145) at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:82) at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:72) at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3939) at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:461) at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:430) at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:207) at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:263) at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:151) at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1017) at org.hibernate.internal.SessionImpl.access$2000(SessionImpl.java:173) at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2413) at org.hibernate.internal.SessionImpl.get(SessionImpl.java:913) at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:807) ... 104 more
While debuging the Hibernate Source I ended up in org.hibernate.loader.Loader.getInstanceClass(...). After entering the if conditition it tries to get the discriminatorValue, which in my test has the value 'testuser'. With this information it tries to get the Subclass from the persister, which fails.
While looking into the Persistener (JoinedSubclassEntityPersister) I found that it maintains a map 'subclassesByDiscriminatorValue'.
This map only contained the following entries: {AdvancedUser = test.AdvancedUser, User = test.User}
I assume there is a bug in this code, either the discriminatorValue should be a class name, or the map should contain a mapping of Id's to their related class names.
Ps.: TestCase was simplified and output was shortened. In case more information are needed I can provide them.
|