3

There have been similar questions in the past, but no real resolution.

I'm converting a Hibernate Web app to be JPA-enabled. There is only 1 DAO class so far, and it's already giving the following error after conversion to JPA.

Note: We are not using Spring-Boot, so prior answers don't apply in our case.

java.lang.ClassCastException: org.springframework.orm.hibernate5.SessionHolder cannot be cast to org.springframework.orm.jpa.EntityManagerHolder
    at org.springframework.orm.jpa.EntityManagerFactoryUtils.doGetTransactionalEntityManager(EntityManagerFactoryUtils.java:221)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:255)
    at com.sun.proxy.$Proxy42.createQuery(Unknown Source)
    at gov.nih.nci.cbiit.scimgmt.idp.dao.LookupDao.findById(LookupDao.java:52)
    at gov.nih.nci.cbiit.scimgmt.idp.dao.LookupDao$$FastClassBySpringCGLIB$$7b0b6cbb.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:651)
    at gov.nih.nci.cbiit.scimgmt.idp.dao.LookupDao$$EnhancerBySpringCGLIB$$1cd8b9dd.findById(<generated>)
    at gov.nih.nci.cbiit.scimgmt.idp.service.impl.LookupServiceImpl.findById(LookupServiceImpl.java:21)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)

Converted JPA-enabled DAO class, just 1 method:

public class LookupDao {

    private final Logger log = LogManager.getLogger(getClass());

    @PersistenceContext
    private EntityManager entityManager;

    public LookupT findById(long id) throws Exception {

        log.info("Entered: LookupDao.findById(), id = " + id);      

        // Pre-JPA (pre-conversion; note: commented out. No Hibernate Session conflicts)
        // -------
        /*
        log.info("getting lookup id="+id);
        return sessionFactory.getCurrentSession().get(LookupT.class, id);
        */

        // New JPA Approach (converted)
        // ----------------
        CriteriaBuilder crbuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<LookupT> crquery = crbuilder.createQuery(LookupT.class);

        Root<LookupT> root = crquery.from(LookupT.class);
        crquery.where(      
                    (crbuilder.equal(root.get("id"), id))
                ); 

        Query q = entityManager.createQuery(crquery);
        return (LookupT)q.getSingleResult();
    }

Libraries:

  • spring-aop-4.3.2.RELEASE.jar
  • spring-beans-4.3.2.RELEASE.jar
  • spring-context-4.3.2.RELEASE.jar
  • spring-core-4.3.2.RELEASE.jar
  • spring-jdbc-4.3.2.RELEASE.jar
  • spring-web-4.3.2.RELEASE.jar
  • hibernate-commons-annotations-5.0.1.Final.jar
  • hibernate-core-5.2.1.Final.jar
  • hibernate-jpa-2.1-api-1.0.0.Final.jar

Anything else that may be helpful to debug this?

I've confirmed:

  • No mixing between Hibernate Session and EntityManager, only 1 DAO with 1 method using the EntityManager, everything else is commented out.
  • Not using Spring-Boot

Prior questions on this subject: Spring 4 + Hibernate 5 = org.springframework.orm.jpa.EntityManagerHolder cannot be cast to org.springframework.orm.hibernate5.SessionHolder

ClassCastException: org.springframework.orm.jpa.EntityManagerHolder cannot be cast to org.springframework.orm.hibernate5.SessionHolder

gene b.
  • 10,512
  • 21
  • 115
  • 227

1 Answers1

3

SOLVED

Our applicationContext.xml had the following bean definition

<bean id="transactionManager"
    class="org.springframework.orm.hibernate5.HibernateTransactionManager"
    p:sessionFactory-ref="sessionFactory" />

which had to be replaced with

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceXmlLocation" value="/META-INF/persistence.xml" />
</bean>

Also, put persistence.xml into the location specified there, META-INF/persistence.

So the key point is that the JpaTransactionManager has to replace the HibernateTransactionManager, and the beans approprioately configured.

gene b.
  • 10,512
  • 21
  • 115
  • 227