如果自动增量字段不是第一个,jOOQ 可以支持复合主键吗
Posted
技术标签:
【中文标题】如果自动增量字段不是第一个,jOOQ 可以支持复合主键吗【英文标题】:Can jOOQ support composite primary keys if auto-increment field isn't the first one 【发布时间】:2021-08-24 04:03:56 【问题描述】:我正在使用 jOOQ (3.14.11) 来管理定义的表(在 H2 或 mysql 中):
CREATE TABLE example_one (
group_id VARCHAR(36) NOT NULL,
pawn_id INT UNSIGNED AUTO_INCREMENT NOT NULL,
some_unimportant_attribute INT UNSIGNED DEFAULT 0 NOT NULL,
another_uniportant_attribute VARCHAR(36),
CONSTRAINT pk_example_one PRIMARY KEY (group_id, pawn_id)
)
请注意,在此 SQL 中,主键按该顺序指定(组、典当)ID,但它是 pawn_id
,第二个是自动增量/身份列。
jOOQ 似乎不喜欢这种安排。当我尝试使用 Record 对象插入新行时,它不会返回给我“pawnID”值:
ExampleOneRecord r = create.newRecord(EXAMPLE_ONE);
r.setGroup("a group identity");
r.store();
assert r.getPawnId() != null; // <---- FAILS test
深入研究代码,嫌疑人似乎是in AbstractDMLQuery.java method executeReturningGeneratedKeysFetchAdditionalRows,它有这样的逻辑:
// Some JDBC drivers seem to illegally return null
// from getGeneratedKeys() sometimes
if (rs != null)
while (rs.next())
list.add(rs.getObject(1));
对rs.getObject(1)
的调用似乎假设生成的列将始终是主键的第一列。
有没有其他方法可以说服 jOOQ?
【问题讨论】:
那里可能有一个错误,因为 identity / auto_increment 列本身就是一个很好的候选键,在你的情况下应该是主键。将group_id
与自动增量列一起放在该键中的基本原理是什么?使其成为集群索引的一部分?这是我第一次看到这种做法...
是的,我认为这可能是一个相当不寻常的案例。原因部分是由于查询效率(我们有时可能有多个“组”级别),因此我们可以查询和管理“孩子”。还因为我们有多个数据库,并且可能需要在它们之间移动“组”——这会使“pawn_id”不够唯一(并且为它们使用 UUID 会破坏集群并使存储膨胀)。
很有趣,谢谢分享。我将调查这是否是 jOOQ 中可以修复的错误,或者我们是否会在此处遇到 JDBC 驱动程序限制。将返回这里与调查结果
您使用的是哪个 MySQL 版本?在 8.0.24 上,当我尝试您的 CREATE TABLE
时出现此错误:"SQL 错误 [1075] [42000]:表定义不正确;只能有一个自动列,它必须定义为键”。您还有其他独特的限制条件吗?
我无法使用 MySQL 版本 8.0.24、驱动程序版本 mysql:mysql-connector-java:8.0.25
并说唯一约束来重现这一点。我认为 MCVE 在这里会有所帮助:github.com/jOOQ/jOOQ-mcve,但这很可能只是旧服务器或驱动程序版本中的错误。
【参考方案1】:
这是 jOOQ 3.15.1 中 H2 的一个错误:https://github.com/jOOQ/jOOQ/issues/12192
它已在 jOOQ 3.16.0 中为 H2 2.0.202 修复,它现在支持强大的数据更改增量表语法,允许更轻松地从 DML 语句中获取生成的值(它在 H2 版本之前实现,但有一个重大错误:https://github.com/h2database/h2database/issues/2502)
【讨论】:
以上是关于如果自动增量字段不是第一个,jOOQ 可以支持复合主键吗的主要内容,如果未能解决你的问题,请参考以下文章