Hibernate EntityManager with getSessionFactoryGetCurrentSession ()

I changed my application for working with Hibernate EntityManager (from a Hibernate session),
but I have some old codes (I cannot change these codes) which are used in the code below:

getSessionFactory().getCurrentSession() .

I have a bean sessionFactory, so the above code should work, but at runtime I have a HibernateException("No Session found for current thread") , even the code above was executed in the transaction block.

FYI: I checked the transaction resources (in debug mode) and with the EntityManagerFactory key, the session exists, but not under the SessionFactory key.

+2
source share
2 answers

I suggest you do this (it seems hacked, but with outdated code, sometimes required)

This solution uses the Spring TransactionSynchronizationManager and Hibernate 4, but can be adapted to a different version of Hibernate.

Here is the idea: using the custom implementation of CurrentSessionContext in your SessionFactoryBean, and this custom implementation will look for the current transaction in the transaction resources for the entity manager; when it is found, it simply calls the code sent by IIla to receive the hibernation session.

For this:

1. Define the hibernate.current_session_context_class property in hibernateProperties:

 <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> ... <property name="hibernateProperties"> <props> ... <prop key="hibernate.current_session_context_class"> com.example.jpa.HibernateSessionInEntityManager </prop> </props> </property> </bean> <!-- for completness : here are the other relevant beans --> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/> </property> <property name="dataSource" ref="dataSource"/> <property name="packagesToScan" value="com.example.jpa.validator"/> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="dataSource" ref="dataSource" /> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> 

2.Configure your custom CurrentSessionContext: HibernateSessionInEntityManager.java

 import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.context.spi.CurrentSessionContext; import org.hibernate.ejb.EntityManagerImpl; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.springframework.orm.jpa.EntityManagerHolder; import org.springframework.transaction.support.TransactionSynchronizationManager; import javax.persistence.EntityManager; import java.util.Map; public class HibernateSessionInEntityManager implements CurrentSessionContext { public HibernateSessionInEntityManager() { } public HibernateSessionInEntityManager(SessionFactory sessionFactory) { } public HibernateSessionInEntityManager(SessionFactoryImplementor sessionFactory) { } public Session currentSession() throws HibernateException { Map<Object, Object> resourceMap = TransactionSynchronizationManager.getResourceMap(); for(Object v:resourceMap.values()){ if(v instanceof EntityManagerHolder){ return getSessionFromEM(((EntityManagerHolder)v).getEntityManager()); } } return null; } private static Session getSessionFromEM(final EntityManager entityManager) { final Object emDelegate = entityManager.getDelegate(); if (emDelegate instanceof EntityManagerImpl) { return ((EntityManagerImpl) emDelegate).getSession(); } else if (emDelegate instanceof Session) { return (Session) emDelegate; } throw new HibernateException("No Session found"); } } 

Pay attention to all those constructors: Hibernate-4 needs one with SessionFactoryImplementor , and I think Hibernate-3 needs one with SessionFactory . (The no-args constructor is probably not required)

3. Here is a simple test case to verify that it works.

 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:ApplicationContext.xml" }) public class HibernateSessionInEntityManagerTest { @Autowired public SessionFactory sessionFactory; @Test @Transactional public void testGetHibernateSession(){ Session session = sessionFactory.getCurrentSession(); Assert.assertNotNull(session); } } 

Hope this helps. (By the way: good question)

Important note: if you have several EntityManagerFactoryBean, you can choose a good one by studying transactional resources. (i.e., for example, look at the persistenceUnitName of the associated entityManagerFactory object)

+8
source

A shorter implementation of the getSessionFromEM method:

  private static Session getSessionFromEM(final EntityManager entityManager){ return entityManager.unwrap(Session.class); } 
0
source

Source: https://habr.com/ru/post/1215972/


All Articles