You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

问题原因与解决方案

核心原因

  1. 会话上下文配置冲突:手动指定hibernate.current_session_context_class干扰了Spring Boot 2.x的自动事务会话管理,Spring会自动适配会话上下文,手动配置可能导致Session无法绑定到当前事务。
  2. 事务管理器不匹配:同时启用@EnableJpaRepositories却使用HibernateTransactionManager,JPA默认适配JpaTransactionManager,两种管理器共存会导致事务绑定异常。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 14:45:34