Java 在Hibernate/Spring 4升级后,无法将ClassCastException Proxy36转换为SessionImplementor

Java 在Hibernate/Spring 4升级后,无法将ClassCastException Proxy36转换为SessionImplementor,java,spring,hibernate,classcastexception,Java,Spring,Hibernate,Classcastexception,编辑:我不是在问什么是ClassCastException。我想问的是,在Spring4/Hibernate4的这种特定配置下,是什么原因导致了DetachedCriteria出现这种情况。 我正试图将一些遗留代码升级到Spring4/Hibernate4,但我遇到了一个难题,因为Google并没有出现太多问题 我正试图在一个非常简单的Hibernate存储库上运行JUnit测试,但失败了 java.lang.ClassCastException: com.sun.proxy.$Proxy36

编辑:我不是在问什么是ClassCastException。我想问的是,在Spring4/Hibernate4的这种特定配置下,是什么原因导致了DetachedCriteria出现这种情况。

我正试图将一些遗留代码升级到Spring4/Hibernate4,但我遇到了一个难题,因为Google并没有出现太多问题

我正试图在一个非常简单的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)
...
这发生在Hibernate的
org.Hibernate.criteria.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;
}
当它试图设置会话(试图将其强制转换为SessionImplementor)时,它抛出ClassCastException

我怀疑这可能是AOP问题,但不确定从哪里开始寻找

我使用的是Spring
4.3.2.RELEASE
,以及Hibernate
4.3.5.Final

hibernate-context.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>
<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>

hibernate/xxxUploadDocResponseInfo.hbm.xml
${xxx.hibernate.dial}
${xxx.hibernate.showsql}
${xxx.hibernate.hbm2ddl}
${xxx.hibernate.formatsql}
真1,假0
transaction-context.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>
<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:

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();
        }
    });
}
...
}
公共抽象类AbstractHibernateRepository扩展了HibernateDaoSupport{
...
@抑制警告(“未选中”)
受保护的E get(最终DetachedCriteria DetachedCriteria){
返回(E)getHibernateTemplate().execute(新的HibernateCallback()){
公共E-doInHibernate(会议){
Criteria=detachedCriteria.getExecutableCriteria(会话);
criteria.setResultTransformer(criteria.DISTINCT\u ROOT\u实体);
返回(E)条件。uniqueResult();
}
});
}
...
}
请参见

enforceNativeSession
-是否强制将本机Hibernate会话公开给回调代码

如您所见:

受保护会话createSessionProxy(会话会话){
返回(会话)Proxy.newProxyInstance(
session.getClass().getClassLoader(),新类[]{session.Class},
新的CloseHandler(会话));
}
创建的代理仅实现接口
会话
,而不实现接口
会话Implementor


升级到spring boot 2.4.0后,您必须用替换。

在遗留代码上面临同样的问题。通过使用
entityManager.unwrap(SessionImplementor.class)
检索用于我的场景中分离条件的会话来修复此问题。

如果任何人在
fulltextentymanager
中有此问题,@Gardella的答案有效,但是,这建议将Hibernate Search ORM依赖项更新为5.11.6.Final,这也解决了这个问题。

。我知道它必须是一个单一的班轮。非常感谢你的耐心,谢谢。它在SpringBoot2.4.2上运行。