bigywater.tech
Spring · 182

TransactionRequiredException:没有事务时 persist、remove、@Modifying 的提示,以及 readOnly 里 persist 为什么有时不落库

TransactionRequiredException: No EntityManager with actual transaction available 怎么来的?persist、remove、merge 与 @Modifying 各报什么?readOnly 里 persist 为什么有时不落库?这篇在 Spring Boot 4.0.8 上逐个触发。

读行写不行
没有事务时 em.find 能读,em.persist、em.remove、em.merge 都抛 TransactionRequiredException
readOnly 丢数据
readOnly 事务里 persist,SEQUENCE 主键的实体 0 行落库且不报错,IDENTITY 主键的实体 1 行
异常类型会变
@Modifying @Query 没有事务时抛的是 InvalidDataAccessApiUsageException,不是 TransactionRequiredException

persist

实测 · 本机执行输出
  没有事务,em.persist → 异常 TransactionRequiredException:No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call;之后 person 表 0 行,item 表 0 行
  对照:@Transactional 方法里 em.persist → 没有异常;之后 person 表 1 行,item 表 0 行

没有事务抛异常,有事务正常。

find / remove / merge

实测 · 本机执行输出
  没有事务,em.find 读到:Person 对象
  没有事务,em.remove → 异常 TransactionRequiredException:No EntityManager with actual transaction available for current thread - cannot reliably process 'remove' call
  没有事务,em.merge → 异常 TransactionRequiredException:No EntityManager with actual transaction available for current thread - cannot reliably process 'merge' call;之后 person 表 0 行,item 表 0 行

读不需要事务,写需要。

@Modifying

实测 · 本机执行输出
  Spring Data 的 save(自带 @Transactional) → 没有异常;之后 person 表 1 行,item 表 0 行
  @Modifying @Query 没有事务 → 异常 InvalidDataAccessApiUsageException:No active transaction for update or delete query
  同一条查询,方法上加 @Transactional → 影响 2 行
  em.createQuery(update …).executeUpdate() 没有事务 → 异常 TransactionRequiredException:No active transaction for update or delete query;之后 person 表 0 行,item 表 0 行

Spring Data 转换了异常类型。

readOnly

实测 · 本机执行输出
  @Transactional(readOnly = true) 里 em.persist(Person,主键 IDENTITY) → 没有异常;之后 person 表 1 行,item 表 0 行
  @Transactional(readOnly = true) 里 em.persist(Item,主键 SEQUENCE) → 没有异常;之后 person 表 0 行,item 表 0 行
  对照:普通 @Transactional 里 em.persist(Item,主键 SEQUENCE) → 没有异常;之后 person 表 0 行,item 表 1 行

IDENTITY 落库,SEQUENCE 不落库也不报错。

自调用

实测 · 本机执行输出
  外层方法没有事务,同类里调用 @Transactional 方法(自调用) → 异常 TransactionRequiredException:No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call;之后 person 表 0 行,item 表 0 行

不经过代理就没有事务。

新线程

实测 · 本机执行输出
  @Transactional 方法里新开线程 em.persist → 异常 RuntimeException ← TransactionRequiredException:No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call;之后 person 表 0 行,item 表 0 行

事务绑在线程上。

分步演示

TxRequired
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK 21.0.12(Homebrew) / Spring Boot 4.0.8(Spring Framework 7.0.9、Tomcat 11.0.24) / Spring Cloud 2025.1.3;用 javac 编译、java 直接运行,依赖由 Maven 从 Maven Central 解析;数字每次运行会有小幅抖动(Spring Boot 4.0.8,Hibernate 7.2,H2 内存库;Svc 通过 @PersistenceContext 注入 EntityManager;Person 主键 IDENTITY,Item 主键 SEQUENCE;每次调用前清空 person 与 item 表,调用后用 JdbcTemplate 数行数)
    • 没有验证:MySQL、PostgreSQL 上 readOnly 事务里 persist 的结果(只在 H2 上测);readOnly 事务里 persist SEQUENCE 主键的数据为何没有落库的内部原因(只看到结果,没有查 flush 模式);saveAll 和 flush 手动调用的影响;@Transactional(propagation = SUPPORTS) 的行为;JpaTransactionManager 与 JTA 下的差异;Boot 3.5 下的措辞对照
    京ICP备2026067502号-1京公网安备11010502063487号