[英]ClassCastException Proxy36 cannot be cast to SessionImplementor after Hibernate/Spring 4 upgrade
EDIT: I am not asking what a ClassCastException is.编辑:我不是在问 ClassCastException 是什么。 I am asking what is causing it in DetachedCriteria under this specific configuration of Spring 4/Hibernate 4.
我在问在 Spring 4/Hibernate 4 的这个特定配置下是什么导致它在 DetachedCriteria 中。
I'm trying to upgrade some legacy code to Spring 4/Hibernate 4 and I've hit a wall, as Google isn't turning up much.我正在尝试将一些遗留代码升级到 Spring 4/Hibernate 4,但我遇到了困难,因为 Google 并没有出现太多问题。
I am trying to run a JUnit test on a very simple Hibernate repository, and it is failing with我正在尝试在一个非常简单的 Hibernate 存储库上运行 JUnit 测试,但它失败了
java.lang.ClassCastException: com.sun.proxy.$Proxy36 cannot be cast to org.hibernate.engine.spi.SessionImplementor
at org.hibernate.criterion.DetachedCriteria.getExecutableCriteria(DetachedCriteria.java:84)
at com.my.app.rest.domain.repository.AbstractHibernateRepository$6.doInHibernate(AbstractHibernateRepository.java:163)
...
This is happening in Hibernate's org.hibernate.criterion.DetachedCriteria
class:这发生在 Hibernate 的
org.hibernate.criterion.DetachedCriteria
类中:
/**
* Get an executable instance of Criteria to actually run the query.
*
* @param session The session to associate the built Criteria with
*
* @return The "executable" Criteria
*/
public Criteria getExecutableCriteria(Session session) {
impl.setSession( (SessionImplementor) session );
return impl;
}
When it tries to set the Session (which attempts to cast it to a SessionImplementor), it throws the ClassCastException.当它尝试设置 Session(试图将其转换为 SessionImplementor)时,它会抛出 ClassCastException。
I suspect this may be an AOP issue, but am not sure where to start looking.我怀疑这可能是 AOP 问题,但我不确定从哪里开始寻找。
I'm using Spring 4.3.2.RELEASE
, and Hibernate 4.3.5.Final
.我正在使用 Spring
4.3.2.RELEASE
和 Hibernate 4.3.5.Final
。
hibernate-context.xml:休眠上下文.xml:
<bean id="xxxSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="xxxDataSource" />
<property name="mappingResources">
<list>
<value>hibernate/xxxUploadDocResponseInfo.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${xxx.hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${xxx.hibernate.showsql}</prop>
<prop key="hibernate.hbm2ddl.auto">${xxx.hibernate.hbm2ddl}</prop>
<prop key="format_sql">${xxx.hibernate.formatsql}</prop>
<prop key="hibernate.query.substitutions">true 1, false 0</prop>
</props>
</property>
<alias name="xxxSessionFactory" alias="sessionFactory" />
</bean>
transaction-context.xml:事务上下文.xml:
<bean id="xxxTransactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:advice id="xxxTxAdvice" transaction-manager="xxxDatasourceTransactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
<!-- all methods begin with save have the transaction -->
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="remove*" propagation="REQUIRED"/>
<tx:method name="inactivate*" propagation="REQUIRED"/>
<tx:method name="complete*" propagation="REQUIRED"/>
<tx:method name="reset*" propagation="REQUIRED"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="flag*" read-only="true"/>
<tx:method name="doWork*" propagation="REQUIRES_NEW" />
</tx:attributes>
</tx:advice>
<bean id="xxxDatasourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="xxxDataSource" />
</bean>
<aop:config>
<aop:pointcut id="allBusiness" expression="execution(public * com.blah.xxx.rest.business.*Business.*(..))"/>
<aop:advisor advice-ref="xxxTxAdvice" pointcut-ref="allBusiness"/>
</aop:config>
AbstractHibernateRepository.java: AbstractHibernateRepository.java:
public abstract class AbstractHibernateRepository<E extends Entity, S extends Serializable> extends HibernateDaoSupport {
...
@SuppressWarnings("unchecked")
protected E get(final DetachedCriteria detachedCriteria) {
return (E) getHibernateTemplate().execute(new HibernateCallback<E>() {
public E doInHibernate(Session session) {
Criteria criteria = detachedCriteria.getExecutableCriteria(session);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
return (E) criteria.uniqueResult();
}
});
}
...
}
Faced same issue on legacy code after upgrade to spring boot 2.4.0.升级到 spring boot 2.4.0 后,在遗留代码上遇到了同样的问题。 Fixed by using
entityManager.unwrap(SessionImplementor.class)
to retrieve the session to be used for DetachedCriteria in my scenario.在我的场景中,通过使用
entityManager.unwrap(SessionImplementor.class)
检索要用于 DetachedCriteria 的会话来修复。
See HibernateTemplate#doExecute见HibernateTemplate#doExecute
enforceNativeSession
- whether to enforce exposure of the native Hibernate Session to callback codeenforceNativeSession
-是否强制本地Hibernate的Session暴露于回调代码
As you can see at GrepCode :正如您在GrepCode 中看到的:
protected Session createSessionProxy(Session session) { return (Session) Proxy.newProxyInstance( session.getClass().getClassLoader(), new Class<?>[] {Session.class}, new CloseSuppressingInvocationHandler(session)); }
the created proxy implements only the interface Session
not the interface SessionImplementor
.创建的代理仅实现接口
Session
而不是接口SessionImplementor
。
You have to replace HibernateTemplate#execute with HibernateTemplate#executeWithNativeSession .你必须用HibernateTemplate#executeWithNativeSession替换HibernateTemplate#execute 。
如果有人在FullTextEntityManager
遇到此问题,@Gardella 的答案有效,但是,此链接建议将 Hibernate Search ORM 依赖项更新为 5.11.6.Final,这也解决了该问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.