我在一个Sping Boot 项目中工作,它不是很老,但应该算是有点遗产。出于某种原因,有人决定在测试中使用内存中的HSQL数据库,不幸的是在1.X版本中。我正在尝试将其升级到最新版本2.X。
升级依赖项后,很多测试停止工作。版本1.X和2.X之间有一些关键的变化,即:读取未提交是旧版本中的默认隔离级别,现在事务模型不同了(我使用MVCC)。
我在应用程序中发现了一个有趣的案例。让我们假设我有两个表:Second
与一些列和First
与id, second_id
和其他列。second_id
是一个外键。现在,我开始一个测试,有一个SQL脚本插入两行:
Second
表:一行id=1
,First
表:一行id=1
,second_id=null
。
脚本以COMMIT
指令结束,因此这些行被提交。因此,在执行脚本之后,我们有两行没有通过外键链接在一起。
现在,在应用程序内部,新事务开始(通过@Transactional
,传播= REQUIRED
)。事务尝试对Second
表(UPDATE Second SET ... WHERE id=1
)中具有id=1
的行运行更新查询。事务正在进行,尚未提交。
这段代码调用了另一个@Transactional
方法,但是使用的是propagation=REQUIRES_NEW
。当前事务被挂起,新事务正在生成。在它内部,执行以下查询:update First set second_id=1 where id=1
-所以基本上我们想通过一个外键将两行链接在一起。但是,它在foreign key no parent
上失败了。
这里发生了什么:我们尝试链接的行当前正在被第一个事务修改,并且它对新事务不可见。但失败了。根据HSQLDB事务模型,这似乎是意料之中的,与其他关系型数据库相比,这有点奇怪。
你知道如何在不修改现有代码的情况下使它工作吗?我只能触摸测试和它们的配置。代码多年来一直运行良好(是的,我知道设计不好),我不允许修改任何与交易相关的东西。有很多新的事务是从REQUIRES_NEW
传播开始的,即使在一些简单的情况下,我认为这是一种过度。
我将非常感谢任何关于如何进行这一工作的想法。
1条答案
按热度按时间3duebb1j1#
最近修复了HSQLDB的问题。见下文:
https://sourceforge.net/p/hsqldb/bugs/1684/
您可以从SVN快照构建jar并将其用于测试。