Pie*_*man 9 spring hibernate jpa transactions spring-data-jpa
我正在开发一个使用Spring框架(4.3.3.RELEASE)和Hibernate(5.2.3.Final)的项目,我开始使用Spring Data JPA.
我刚刚迁移LocalSessionFactoryBean与HibernateTransactionManager配置使用的JPA的配置LocalContainerEntityManagerFactoryBean与JpaTransactionManager使用HibernateJpaSessionFactoryBean.
使用Sessions中的SessionFactorys 的现有hibernate代码似乎工作正常,直到我测试了一些代码执行一个实体的保存,然后在同一个事务中运行一些更新查询,并且代码在更新sql上失败:
javax.persistence.TransactionRequiredException: Executing an update/delete query
Run Code Online (Sandbox Code Playgroud)
事务管理器日志显示事务处于活动状态,然后回滚,这很奇怪.然后我注意到保存操作已到达数据库.
在调试时我可以看到会话对象似乎没有任何事务对象,因此似乎hibernate会话不使用或使用已配置的JpaTransactionManager事务.
当我配置HibernateTransactionManager标记为主要PlatformTransactionManager的附加事务管理器()时,代码然后工作.
接下来,当我将代码迁移到Spring Data Jpa时,我将希望在同一个Transaction中使用一些基于Hibernate的Dao代码和一些Spring Data Jpa Repository.如何让会话工厂使用JpaTransactionManager?
更新:
我现在发现上面的配置意味着事务管理器不会将会话刷新到数据库,因此无法正常工作.
我还发现,如果我将EntityManager注入到我的Daos中:
@PersistenceContext()
private EntityManager entityManager;
Run Code Online (Sandbox Code Playgroud)
并使用:
entityManager.unwrap( Session.class )
Run Code Online (Sandbox Code Playgroud)
然后代码正确地参与事务.但是如果我得到SessionFactory(通过spring注入,或者从unwrap中解包entityManagerFactory,或者getSessionFactory()从unwrap中使用Session)并调用getCurrentSession()它,则返回一个未连接到事务的不同Session对象.
我的配置:
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1120 次 |
| 最近记录: |