首页 > 解决方案 > 更新寄存器时休眠(JpaRepository)中的完整性约束问题

问题描述

我在数据库中有两个表,A 和 B。按以下方式定义:

CREATE TABLE A (
id NUMBER,
Name VARCHAR(100),
  CONSTRAINT pk_id PRIMARY KEY (id)
);

CREATE TABLE B (
id NUMBER,
a_id NUMBER,
  CONSTRAINT pk_id PRIMARY KEY (id),
  CONSTRAINT id_a_id FOREIGN KEY (a_id) REFERENCES a(id)
);

我想要做的是使用 JpaRepository 更新 A 表的寄存器“让我们假设 id:5”,当 B 表有一个带有 a_id:5 的寄存器时。

为此,您尝试的第一个想法是从 A 数据库中获取实体,修改 Name 值,删除旧寄存器并保存一个带有更改的新寄存器:

@Transactional
void update()
{
 List<A> oldARegisterList = a.findById(5);
 A oldARegister = oldARegisterList.get(0);
 A newRegister = new A(oldARegister);
 a.delete(oldARegister);
 newRegister.setName("NewName");
 a.save(newRegister);
}

但我得到一个 ORA-02291: 违反完整性约束 (id_a_id) - 找不到父键。

然后我尝试删除 B 中的寄存器,删除并使用新名称在 A 中创建寄存器,最后在 B 中再次创建寄存器:

@Transactional
void update()
{
 List<A> oldARegisterList = a.findById(5);
 A oldARegister = oldARegisterList.get(0);
 B oldBRegister = oldARegister.getB();
 b.delete(oldBRegister);
 A newRegister = new A(oldARegister);
 a.delete(oldARegister);
 newRegister.setName("NewName");
 a.save(newRegister);
 b.save(oldBRegister);
}

它不工作以太给出同样的问题,但如果我手动执行首先删除 B 寄存器,然后更新 A 寄存器,最后重新创建 B 寄存器它可以工作。

所以看起来如果delete B update A和recreate B的过程在同一个事务中,这个过程是行不通的。

怎么可能在同一个事务中做到这一点?

非常感谢。

标签: javasqloraclespring-data-jpa

解决方案


作为第一个注释,我应该注意到您可以简单地更新oldARegister名称而不删除oldBRegister,因为名称不是 A 上的主键,所以只需使用这个:

oldARegister.setName("New Name");
a.save(oldARegister);

但是如果你想在路上做,你应该把 A of 设置oldBRegisternewRegister这样:

oldBRegister.setA(newRegister)
b.save(oldBRegister);

推荐阅读