java 鉴别器,带有 Hibernate 后端的 WrongClassException JPA
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4334197/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Discriminator , WrongClassException JPA with Hibernate backend
提问by Satish Kumar
I have a requirement to have an abstract superclass.
我有一个抽象超类的要求。
I have 6 subclasses for that abstract superclass.
我有该抽象超类的 6 个子类。
I mapped them with the SINGLE_TABLE inheritance strategy in JPA.
我用 JPA 中的 SINGLE_TABLE 继承策略映射了它们。
In another POJO I have a one to many relationship with these 1+6 classes.
在另一个 POJO 中,我与这些 1+6 类有一对多的关系。
@OneToMany(mappedBy = "mSearchPreference", cascade = CascadeType.ALL)
private Set<SearchCriteria> mSearchCriteria;
here "SearchCriteria" is the abstract class.
这里“SearchCriteria”是抽象类。
@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
它有 6 个具体的子类,比如
@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.Loader.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?
有谁知道解决方案?
回答by sdespolit
you should use @org.hibernate.annotations.DiscriminatorOptions(force=true)
on your root entity
你应该@org.hibernate.annotations.DiscriminatorOptions(force=true)
在你的根实体上使用
回答by Ralph
Your stack trace looks like if you are layz loading an set of SearchCriteria enities.
如果您正在加载一组 SearchCriteria 实体,您的堆栈跟踪看起来像。
for example: @OneToMany(mappedBy = "mSearchPreference", cascade = CascadeType.ALL) private Set mSearchCriteria;
例如:@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.
问题是 Hibernate 在不加载实体的情况下无法知道正确的子类。所以如果集合是通过延迟加载创建的,hibernate 首先为集合中的所有实体创建 SearchCriteria 类型的代理。如果稍后加载 concreate 实例,则无法通过正确的代理交换未创建足够多的代理。
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.
因此,“修复”是不使用代理。这意味着您要么必须使用预先加载(lazy="false")或lazy="no-proxy"。后一个选项需要对编译类进行字节码操作,以使 Hibernate 拦截对 getter 方法的调用(请参阅 http://www.hibernate.org/hib_docs/v3/re... 属性)。我没有使用这种方法的经验,但它似乎很适合您的情况。
https://forum.hibernate.org/viewtopic.php?f=1&t=996047&start=0
https://forum.hibernate.org/viewtopic.php?f=1&t=996047&start=0