使用Micronaut Data框架遇Hibernate事务同步Session获取失败求助
解决Micronaut Data + Hibernate中"Could not obtain transaction-synchronized Session for current thread"错误
错误信息
19:53:29.910 [default-nioEventLoopGroup-1-2] ERROR i.m.http.server.RouteExecutor - Unexpected error occurred: Could not obtain transaction-synchronized Session for current thread org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread at io.micronaut.transaction.hibernate.MicronautSessionContext.currentSession(MicronautSessionContext.java:61)
问题分析
Hibernate执行数据库操作时,必须依赖线程绑定的事务同步Session。你调用repository.findOne(spec)时,当前线程未处于事务上下文内,导致Hibernate无法获取到绑定的Session,从而抛出该异常。
解决方案
在事务边界添加@Transactional注解,推荐在Service层方法上添加(更符合业务事务边界的设计原则),也可直接在Repository接口上添加。
方案1:Service层添加@Transactional(推荐)
修改Service实现类,在目标方法上标注@Transactional:
@Slf4j @Singleton @AllArgsConstructor public class MyServiceImpl implements MyService { private final MyRepository repository; @Override @Transactional // 开启事务上下文 public List<TimeSeriesEntryDto<Long>> getMyEntity(Specification<MyEntity> spec) { final Optional<MyEntity> result = repository.findOne(spec); // 后续业务逻辑处理... } }
方案2:Repository层添加@Transactional
如果希望所有Repository方法默认在事务中执行,可直接在Repository接口上标注:
@Repository @Transactional // 所有Repository方法默认开启事务 public interface MyRepository extends PageableRepository<MyEntity, Long>, JpaSpecificationExecutor<MyEntity> { }
原理说明
- Micronaut Data的Repository接口默认不会自动开启事务,必须通过
@Transactional显式声明事务边界。 - 标注
@Transactional后,Micronaut事务管理器会自动完成以下操作:- 方法执行前创建Hibernate Session并绑定到当前线程
- 数据库操作时,Hibernate通过
currentSession()获取线程绑定的Session - 方法执行完成后,自动提交事务(无异常时)或回滚事务(发生异常时)
- 你遇到的错误本质就是缺少线程绑定的Session,而事务上下文正是创建并绑定Session的必要条件。
补充配置说明
你的JPA配置hibernate.hbm2ddl.auto: none是正常的,和当前错误无关,该配置仅用于关闭Hibernate自动生成表结构的功能。
内容的提问来源于stack exchange,提问作者Rafael_Codemaker
相关产品推荐
相关产品推荐

