如果自动增量字段不是第一个,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 可以支持复合主键吗的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 死锁与复合主键和触发自动增量

将 MyISAM 转换为 InnoDB,其中表具有两列(复合)PK,其中之一是自动增量

MySQL 多行插入是不是获取顺序自动增量 ID?

如何在流星上创建自动增量字段?

Oracle 复合索引设计原理——前缀性和可选性

复合主键?还是具有唯一复合索引的自动增量主键? [关闭]