升级In-memory HSQLDB 2.X后REQUIRES_NEW事务传播异常问题
解决HSQLDB 2.X升级后跨事务外键校验失败问题
问题根源
HSQLDB 2.X默认采用MVCC事务模型,默认隔离级别为读已提交;而1.X版本使用锁基事务模型,默认隔离级别为读未提交。这种差异导致:在@Transactional(propagation=REQUIRED)事务中修改的Second表数据,未提交时,后续@Transactional(propagation=REQUIRES_NEW)的新事务无法读取到该修改,触发外键约束错误。
可行解决方案(不修改业务代码)
1. 全局调整HSQLDB配置,回退至1.X兼容模式
通过JDBC URL参数修改事务模型和默认隔离级别,让HSQLDB 2.X表现和1.X一致:
在测试环境的application-test.properties中配置:
spring.datasource.url=jdbc:hsqldb:mem:testdb;transaction_model=LOCKING;default_isolation_level=READ_UNCOMMITTED
transaction_model=LOCKING:关闭MVCC,使用1.X的锁基事务模型default_isolation_level=READ_UNCOMMITTED:保持旧版默认隔离级别,允许新事务读取未提交数据
2. 调整测试数据初始化逻辑
如果不想修改全局DB配置,可在测试脚本层面调整:
- 提前在测试数据插入阶段建立
First和Second的关联,将First的second_id直接设为1,跳过后续跨事务的更新操作 - 或者在测试中,控制第一个事务执行UPDATE后先提交,再触发
REQUIRES_NEW方法(需确保测试的事务控制逻辑不影响业务代码)
3. 测试环境临时禁用外键约束(兜底方案)
仅在测试环境临时关闭外键校验,避免跨事务的约束错误:
- 测试启动时执行SQL:
SET DATABASE REFERENTIAL INTEGRITY FALSE;
- 测试结束后恢复:
SET DATABASE REFERENTIAL INTEGRITY TRUE;
⚠️ 注意:此方案仅适用于测试环境,生产环境禁用外键会导致数据一致性风险,绝对不可用
推荐方案
优先选择方案1,通过配置直接对齐旧版HSQLDB行为,无需大量修改测试脚本,最贴合业务代码的原有运行逻辑。
内容的提问来源于stack exchange,提问作者rabbitvirus
相关产品推荐
相关产品推荐

