Spring Boot从1.5.4迁移到2.7.5时遭遇TransactionRequiredException异常
Spring Boot 1.5.4 迁移至2.7.5后Hibernate事务异常排查与解决
问题场景
将Spring Boot应用从1.5.4版本迁移至2.7.5版本,DAO层基于Hibernate实现。调用DAO的更新方法时,尽管Service类已添加类级别@Transactional注解,仍抛出TransactionRequiredException异常。
现有配置与代码
配置文件参数
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext
主应用类注解
@EnableTransactionManagement @EnableJpaRepositories(basePackages = {"repository package"}) @ComponentScan(basePackages = {"base package"}) @EntityScan(basePackages = {"entity package"})
DAO核心代码
private EntityManager entityManager; private Session getSession() { return entityManager.unwrap(Session.class); } // 抛出异常的核心方法 public void doSomething(){ String hqlBuilder = "Update Query statement"; Query query = getSession().createQuery(hqlBuilder); int result = query.executeUpdate(); }
事务管理器配置
@Autowired HikariDataSource dataSource; @Bean public LocalSessionFactoryBean sessionFactory() { LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); sessionFactory.setDataSource(dataSource); sessionFactory.setPackagesToScan( new String[]{"<My packages>"}); //sessionFactory.setHibernateProperties(hibernateProperties()); return sessionFactory; } @Bean public PlatformTransactionManager transactionManager() { HibernateTransactionManager hibernateTransactionManager = new HibernateTransactionManager(); hibernateTransactionManager.setSessionFactory(sessionFactory().getObject()); return hibernateTransactionManager; }
抛出的异常信息
首次触发异常
Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:445) at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1692) at <removed the package path>.dao.impl.LastViewedHistoryElementDaoHibernate.insertOrUpdate(LastViewedHistoryElementDaoHibernate.java:122) at impl.LastViewedHistoryElementDaoHibernate$$FastClassBySpringCGLIB$$f8fba493.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ... 271 common frames omitted
重复触发异常
Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:445) at org.hibernate.internal.SessionImpl.checkTransactionNeededForUpdateOperation(SessionImpl.java:3496) at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1399) at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1394) at org.springframework.orm.hibernate5.SessionFactoryUtils.flush(SessionFactoryUtils.java:113) at org.springframework.orm.hibernate5.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:95) at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:97) at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:916) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:727) at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711) at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:654) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:407) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
问题原因与解决方案
核心原因
- 会话上下文配置冲突:手动指定
hibernate.current_session_context_class干扰了Spring Boot 2.x的自动事务会话管理,Spring会自动适配会话上下文,手动配置可能导致Session无法绑定到当前事务。 - 事务管理器不匹配:同时启用
@EnableJpaRepositories却使用HibernateTransactionManager,JPA默认适配JpaTransactionManager,两种管理器共存会导致事务绑定异常。 - EntityManager注入不规范:DAO中
EntityManager未通过Spring标准方式注入,导致获取的Session不在事务范围内。
解决方案步骤
1. 移除手动会话上下文配置
删除配置文件中的以下参数:
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext
Spring Boot 2.x会自动配置Hibernate会话上下文为SpringSessionContext,无需手动干预。
2. 替换为JPA事务管理器
将原HibernateTransactionManager配置替换为适配JPA的事务管理器:
@Bean public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(entityManagerFactory); return transactionManager; }
同时可以移除LocalSessionFactoryBean的手动配置,EntityManagerFactory会由Spring Boot自动创建,除非有特殊Hibernate自定义需求。
3. 规范EntityManager注入
DAO中的EntityManager通过@PersistenceContext注解注入,确保Spring将其与当前事务绑定:
@PersistenceContext private EntityManager entityManager;
4. 验证事务注解生效
- 确认Service类在
@ComponentScan指定的包路径下,被Spring正确扫描。 - 避免Service内部方法自调用(Spring AOP基于代理实现,内部调用不会触发事务拦截)。
- 可尝试将
@Transactional添加到具体方法上,而非仅类级别,确保注解被正确识别。
5. 避免覆盖自动配置
使用spring-boot-starter-data-jpa依赖时,大部分JPA/Hibernate配置会自动完成,无需手动创建SessionFactory或EntityManagerFactory,减少配置冲突。
验证
修改配置后重启应用,调用Service触发DAO更新操作,确认TransactionRequiredException不再抛出,事务正常提交。
内容的提问来源于stack exchange,提问作者Kiran Pophale
相关产品推荐
相关产品推荐

