@Transactional(readOnly = true) 只是个提示吗?MySQL 那边到底收到了什么?Hibernate 里改了实体会怎样?内层方法标 readOnly 有用吗?这篇在 Spring Framework 7.0.9、Hibernate 和 MySQL 26.7.0 上逐项验证。
readOnly = true 的方法执行时,那个连接上的语句:
SET SESSION TRANSACTION READ ONLY
SET autocommit=0
select balance from acct where id = 1
COMMIT
SET autocommit=1
SET SESSION TRANSACTION READ WRITE
readOnly = true 里用 JdbcTemplate 写:失败 TransientDataAccessResourceException ← SQLException: Connection is read-only. Queries leading to data modification are not allowed.;表里 balance = 100
readOnly = false(默认)里用 JdbcTemplate 写:成功;表里 balance = 500readOnly 对应会话级的 READ ONLY / READ WRITE 切换,驱动在客户端拒绝写入。
readOnly = true:修改受管实体 a.balance = 777,事务结束 → 表里 balance = 100(100 表示没有写进去)
这次的 SQL 里有 UPDATE 吗?false
readOnly = false:同样的修改 → 表里 balance = 777;SQL 里有 UPDATE 吗?true
readOnly = true 里修改实体后手动 em.flush():成功;表里 balance = 100只读事务里实体修改不会被刷新,手动 flush 也不报错。
外层读写事务里调用 readOnly = true 的内层方法(REQUIRED 加入外层事务):成功,返回 外层读写,里层 readOnly=true 的方法写成功了;表里 balance = 321;(内层方法是经过代理调用的,不是自调用) 单独调用 readOnly = true 的 roFlag():readOnly=true
内层的 readOnly 对已有的读写事务无效。