插入新的 UpdatableRecord 并在重复主键上接收错误
问题:插入新的 UpdatableRecord 并在重复主键上接收错误 我正在尝试在 jOOQ 3.4.2 中使用 UpdatableRecords 插入新记录。该模式非常简洁且易于使用,除了INSERT将空值读取为无值并忽略默认值或生成的索引。如何使用 UpdatableRecord 执行尊重默认值和生成索引的插入? 这是我的桌子: CREATE TABLE aragorn_sys.org_pe
问题:插入新的 UpdatableRecord 并在重复主键上接收错误
我正在尝试在 jOOQ 3.4.2 中使用 UpdatableRecords 插入新记录。该模式非常简洁且易于使用,除了INSERT
将空值读取为无值并忽略默认值或生成的索引。如何使用 UpdatableRecord 执行尊重默认值和生成索引的插入?
这是我的桌子:
CREATE TABLE aragorn_sys.org_person (
org_person_id SERIAL NOT NULL,
first_name CHARACTER VARYING(128) NOT NULL,
last_name CHARACTER VARYING(128) NOT NULL,
created_time TIMESTAMP WITH TIME ZONE DEFAULT current_timestamp NOT NULL,
created_by_user_id INTEGER,
last_modified_time TIMESTAMP WITH TIME ZONE,
last_modified_by_user_id INTEGER,
org_id INTEGER NOT NULL,
CONSTRAINT PK_org_person PRIMARY KEY (org_person_id)
);
注意我的主键和默认值。现在这是我的 jOOQ 代码:
// orgPerson represents a POJO filled with my values to be inserted and null for everything else
// Note that orgPerson.orgPersonId is null
OrgPersonRecord orgPersonRecord = create.newRecord( ORG_PERSON, orgPerson );
Integer orgPersonId = create.executeInsert( orgPersonRecord );
但是当我运行它时,我得到了错误null value in column "org_person_id" violates not-null constraint
。
我注意到 jOOQ 文档说调用newRecord
会自动在 UpdatableRecord 上将所有内部“已更改”标志设置为 true。所以我尝试了这个:
// orgPerson represents a POJO filled with my values to be inserted and null for everything else
// Note that orgPerson.orgPersonId is null
OrgPersonRecord orgPersonRecord = create.newRecord( ORG_PERSON, orgPerson );
orgPersonRecord.changed( ORG_PERSON.ORG_PERSON_ID, false );
orgPersonRecord.changed( ORG_PERSON.CREATED_TIME, false );
orgPersonRecord.insert()
Integer orgPersonId = orgPersonRecord.getOrgPersonId();
但这给了我错误ERROR: duplicate key value violates unique constraint "pk_org_person"
。当我反复这样做时,值似乎不断增加 1。这对我来说真的没有意义,但我更大的问题是:有没有一种好方法可以根据我的对象值进行 INSERT,或者更好的是,只包含非空列?
我看到JOOQ 忽略了默认值的数据库列,但这似乎并不能解决这个问题。有关处理此问题的最简洁方法的任何建议?
顺便说一句,到目前为止,jOOQ 的合作非常棒。 Lukas,感谢您提供了这个很棒的工具!
更新#1:
Lukas 在下面的回答解决了“非空问题”,这是一个简单的解决方法。
对于重复的主键,我绝对不会混淆INSERT
和UPDATE
。当我运行上述代码时(自原始帖子以来略有更新),jOOQ 似乎为OrgPersonId
任意选择了一个“起始”主键值。例如,当我第一次加载我的环境时,jOOQ 可能以OrgPersonId
的“11”开头。
然后,当我执行INSERT
时,jOOQ 将尝试为OrgPersonId
提供值“11”,我将得到ERROR: duplicate key value
,而INSERT
将失败。如果我然后重复INSERT
,jOOQ 使用“12”,然后使用“13”。它根据该 ID 是否可用而成功或失败,但它不是从正确的 ID“开始”。
手册(http://www.jooq.org/doc/3.4/manual/sql-execution/crud-with-updatablerecords/identity-values/)说If you're using jOOQ's code generator, the above table will generate a org.jooq.UpdatableRecord with an IDENTITY column. This information is used by jOOQ internally, to update IDs after calling store()
。
更新#2:
好的,我只是直接在 Postgres 中尝试了生成的查询,但它在那里也失败了,同样的问题。因此,显然这是 Postgres 问题,而不是 jOOQ 问题。当我找到它时,我会发布最终解决方案,以防其他人遇到这个问题。
更新#3:
问题已解决。我们使用 FlywayDB(另一个很棒的工具)来自动化我们的数据库模式迁移,我们在 Flyway 脚本中有一堆INSERT
语句,这些语句手动插入了 id 号。这很方便,因为我们想创建一堆虚拟数据并希望保证正确的外键关系。
但是手动指定主键增量不会推进 Postgres 序列!因此,在(正确操作)jOOQ 获得正确的序列值之前,我们必须循环遍历 Postgres 序列。
解决方案是在我们的演示数据迁移脚本中删除所有手动插入的主键。
解答
违反非空约束
您描述的第一部分是一个缺陷(#3582),它与上一个问题(#2700)有关,它强制将从 POJO 加载的null
值存储到数据库列的 jOOQRecords
中:NOT NULL
.修复将在 jOOQ 3.5.0、3.4.3、3.3.4 和 3.2.7 中
重复键值违反唯一约束“pk_org_person”
第二部分可能是由于您实际上是在加载现有记录,然后在其上调用executeInsert()
(观察INSERT
,它将始终执行INSERT
语句)。您可能想调用executeUpdate()
,而不是
更多推荐
所有评论(0)