JpaTransactionManager operations not used by a Hibernate session

I am working on a project using Spring framework (4.3.3.RELEASE) and Hibernate (5.2.3.Final), and I'm starting to move on to using Spring JPA data.

I just migrated the LocalSessionFactoryBean configuration with HibernateTransactionManager to the JPA LocalContainerEntityManagerFactoryBean configuration with JpaTransactionManager using HibernateJpaSessionFactoryBean .

The existing hibernation code that uses Session from SessionFactory seems to work fine until I check some code that saves only one object and then runs some update requests in a single transaction and the code doesn't work when updating sql with:

 javax.persistence.TransactionRequiredException: Executing an update/delete query 

Transaction manager logs showed that the transaction was active and then roll back, which was strange. Then I noticed that the save operation reached the database.

When debugging, I see that the session object has no transaction object, so it seems that the hibernate session is not working or not using the configured JpaTransactionManager transactions.

When I configure an additional transaction manager ( HibernateTransactionManager ), marked as the primary PlatformTransactionManager , then the code works.

Moving forward, when I port the code to Spring Data Jpa, I want to use some Hibernate based Dao code and some Spring Data Jpa repository in the same transaction. How can I get a factory session to use JpaTransactionManager ?

UPDATE:

Now I have found that the above configuration means that the session is not dumped into the database by the transaction manager, therefore it does not work correctly.

I also found that if I introduce EntityManager in my Daos:

 @PersistenceContext() private EntityManager entityManager; 

and use:

 entityManager.unwrap( Session.class ) 

Then the code is involved in the transaction correctly. But if I get a SessionFactory (either entered by spring, or deployed from entityManagerFactory , or using getSessionFactory() from the deployed Session ), and the call to getCurrentSession() , it returns another session object that is not connected to the transaction.

My configuration:

  @Configuration @EnableJpaRepositories( basePackages = "com.mycompany.common.services", transactionManagerRef = "jpaTransactionManager" ) @EnableTransactionManagement(order = 5) public class PersistenceConfiguration { @Bean @Qualifier(value = "entityManagerFactory") public LocalContainerEntityManagerFactoryBean entityManagerFactory( DataSource dataSource ) { LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setPersistenceUnitName( "entityManagerFactory" ); factory.setPackagesToScan( entityPackages() ); factory.setJpaVendorAdapter( getHibernateJpaVendorAdapter() ); factory.setJpaProperties( getJpaProperties() ); factory.setDataSource( dataSource ); factory.afterPropertiesSet(); return factory; } @Bean @Qualifier(value = "jpaTransactionManager") public PlatformTransactionManager jpaTransactionManager( EntityManagerFactory entityManagerFactory, DataSource dataSource ) { JpaTransactionManager txManager = new JpaTransactionManager(); txManager.setEntityManagerFactory( entityManagerFactory ); txManager.setDataSource( dataSource ); return txManager; } @Bean @Qualifier(value = "sessionFactory") public FactoryBean<SessionFactory> sessionFactory( EntityManagerFactory entityManagerFactory ) { HibernateJpaSessionFactoryBean hibernateJpaSessionFactoryBean = new HibernateJpaSessionFactoryBean(); hibernateJpaSessionFactoryBean.setEntityManagerFactory( entityManagerFactory ); return hibernateJpaSessionFactoryBean; } // How do I remove this and just use the one transaction manager above? /* @Bean @Qualifier(value = "hibernateTransactionManager") @Primary public PlatformTransactionManager hibernateTransactionManager( SessionFactory sessionFactory ) { HibernateTransactionManager hibernateTransactionManager = new HibernateTransactionManager( sessionFactory ); return hibernateTransactionManager; } */ @Bean public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { return new PersistenceExceptionTranslationPostProcessor(); } protected HibernateJpaVendorAdapter getHibernateJpaVendorAdapter() { HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); vendorAdapter.setGenerateDdl( isGenerateDDL() ); vendorAdapter.setDatabase( Database.MYSQL ); vendorAdapter.setDatabasePlatform( com.mycompany.common.utils.hibernate.MySQL56InnoDBDialect.class.getName() ); return vendorAdapter; } protected Properties getJpaProperties() { Properties properties = new Properties(); properties.put("hibernate.current_session_context_class", "org.springframework.orm.hibernate5.SpringSessionContext"); properties.put("hibernate.hbm2ddl.auto", "validate"); properties.put("hibernate.transaction.flush_before_completion", "true"); properties.put("hibernate.transaction.auto_close_session", "false"); properties.put("hibernate.use_outer_join", "true"); properties.put("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory"); properties.put("hibernate.cache.use_second_level_cache", "true"); properties.put("net.sf.ehcache.configurationResourceName", "META-INF/resources/ehcache-hibernate.xml"); properties.put("hibernate.cache.use_query_cache", "true"); properties.put("hibernate.jdbc.batch_size", "100"); properties.put("hibernate.generate_statistics", "true"); properties.put("hibernate.format_sql", "true"); properties.put("hibernate.use_sql_comments", "true"); properties.put("org.hibernate.SQL", "info"); return properties; } protected boolean isGenerateDDL() { return false; } } 
+8
source share

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


All Articles