Discriminator , WrongClassException JPA with Hibernate backend
I have a requirement to have an abstract superclass.
I have 6 subclasses for that abstract superclass.
I mapped them with the SINGLE_TABLE inheritance strategy in JPA.
In another POJO I have a one to many relationship with these 1+6 classes.
@OneToMany(mappedBy = "mSearchPreference", cascade = CascadeType.ALL)
private Set<SearchCriteria> mSearchCriteria;
here "SearchCriteria" is the abstract class.
@Entity
@Table(name = "SRCH_CRTR_T", schema = "LPEW")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "SRCH_DISCRIMINATOR_CDE", discriminatorType = DiscriminatorType.STRING)
@org.hibernate.annotations.ForceDiscriminator
public abstract class SearchCriteria extends BaseDBObject implements Comparable<SearchCriteria>
and it has 6 concrete subclasses classes like
@Entity
@DiscriminatorValue("DATE")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class SearchCriteriaDateRange extends SearchCriteria
I can insert the values into the table, but when I am retrieving I get an error:
Caused by: org.hibernate.WrongClassException: Object with id: 261 was not of the specified subclass: com.lmig.lit.lpew.model.criteria.SearchCriteria (Discriminator: DATE )
at org.hibernate.loader.Loader.getInstanceClass(Loader.java:1453)
at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1284)
at org.hibernate.loader.Loader.getRow(Loader.java:1206)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:580)
at org.hibernate.loader.L
10:57:44,786 INFO [STDOUT] oader.doQuery(Loader.java:701)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
at org.hibernate.loader.Lo开发者_Python百科ader.loadCollection(Loader.java:1994)
at org.hibernate.loader.collection.BatchingCollectionInitializer.initialize(BatchingCollectionInitializer.java:52)
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:565)
at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:63)
at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1716)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:344)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
at org.hibernate.collection.AbstractPersistentCollection.readElementExistence(AbstractPersistentCollection.java:142)
at org.hibernate.collection.PersistentSet.add(PersistentSet.java:187)
at com.lmig.lit.lpew.model.homescreen.HomeScreenPreference.addSearchCriteriaByType(HomeScreenPreference.java:132)
at com.lmig.lit.lpew.model.homescreen.HomeScreenPreference.addSearchCriteriaByType(HomeScreenPreference.java:147)
at com.lmig.lit.lpew.service.LpewUserServiceImpl.initializeHomeScreenPreferences(LpewUserServiceImpl.java:135)
at com.lmig.lit.lpew.service.LpewUserServiceImpl.findUserAndInitialize(LpewUserServiceImpl.java:103)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy122.findUserAndInitialize(Unknown Source)
at com.lmig.lit.lpew.jsf.beans.UserSession.getLpewUser(UserSession.java:989)
at com.lmig.lit.lpew.jsf.beans.RequestForServiceBean.getAllRequests(RequestForServiceBean.java:263)
at com.lmig.lit.lpew.jsf.beans.RequestForServiceBean.getAllNewRequests(RequestForServiceBean.java:382)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at javax.el.BeanELResolver.getValue(BeanELResolver.java:62)
at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:53)
at com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:64)
at org.apache.el.parser.AstValue.getValue(AstValue.java:97)
at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:186)
Does anyone know the solution?
you should use @org.hibernate.annotations.DiscriminatorOptions(force=true)
on your root entity
Your stack trace looks like if you are layz loading an set of SearchCriteria enities.
for example: @OneToMany(mappedBy = "mSearchPreference", cascade = CascadeType.ALL) private Set mSearchCriteria;
The problem is that Hibernate can't know the proper subclass without loading the entity. So if the set is created by lazy loading, hibernate first create proxies of type SearchCriteria for all entities in the set. If the concreate instance is loaded later, than there is no way to exchange the not concreate enough proxy by the right one.
So, the "fix" is to not use proxies. And this means that you either have to use eager loading (lazy="false") or lazy="no-proxy". The latter option requires byte-code manipulation of the compiled classes to make Hibernate intercept the call to the getter method (see http://www.hibernate.org/hib_docs/v3/re ... properties). I have no experience with this method, but it seems like a good candidate for your case.
https://forum.hibernate.org/viewtopic.php?f=1&t=996047&start=0
精彩评论