【问题标题】:JPA sequence generation strategy IDENTITY for AS400 tableAS400表的JPA序列生成策略IDENTITY
【发布时间】:2025-12-12 16:40:01
【问题描述】:

我在我的实体类中提到了序列生成策略 IDENTITY,用于 AS400 系统中表的主键。

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "SEQNO")
private Integer seqNo;

表的主键列在数据库中定义为 GENERATED ALWAYS AS IDENTITY。
SEQNO BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY(START WITH 1, INCREMENT BY 1)
我对 IDENTITY 策略的理解是,它将主键生成责任留给表本身。
我面临的问题是,在某种环境中,在表中插入记录时,它给了我[SQL0803] Duplicate Key value specified.
现在我有几个问题:

  1. 我对@9​​87654324@ 的理解是否正确?
  2. 在哪个场景表会产生 Duplicate key?
  3. 我发现表中缺少序列值,即在4之后,缺少直到20的序列,我不知道是否有人手动删除了它,但这可能与重复密钥生成有关吗?李>

【问题讨论】:

    标签: java hibernate jpa spring-data-jpa ibm-midrange


    【解决方案1】:
    1. 是的。 IDENTITY 表示使用数据存储区中的功能,例如“AUTO_INCREMENT”、“SERIAL”、“IDENTITY”。因此,任何INSERT 都应该省略IDENTITY 列,并在INSERT 执行后将值拉回(针对该对象的内存)。
    2. 永远不应获得重复的密钥。检查正在使用的 INSERT 语句。
    3. 某些外部进程使用同一个表?使用日志查看 SQL 并解决问题。

    【讨论】:

      【解决方案2】:

      我不使用 JPA,但你所拥有的对我来说似乎是合理的。

      就 DB2 for i 而言...

      您确定在身份列上收到重复键错误吗?没有其他列被定义为唯一的吗?

      身份列上可能存在重复键错误。

      你需要意识到的是,下一个标识值存储在表对象中;不是即时计算的。当我开始使用 Identities 时,我被一个 CMS 包所吸引,该包通常使用 CPYF 在新创建的表版本之间移动数据。新版本的表的下一个标识值为 1,即使其中可能有 10 万条记录。 (这个包已经变得更聪明了:)但问题仍然是,例如 CPYF 不能很好地处理标识列。

      此外,可以通过INSERT 语句的OVERRIDING SYSTEM VALUEOVERRIDING USER VALUE 子句覆盖GENERATED ALWAYS。但是使用覆盖插入对存储的下一个标识值没有影响。我想可以将 CPYF 视为使用OVERRIDING SYSTEM VALUE

      现在,至于您丢失的身份...

      1. 数据已删除
      2. 数据被复制并覆盖了身份
      3. 有人ALTER TABLE <...> ALTER COLUMN <...> RESTART WITH
      4. 您失去了对某些值的使用

      让我解释一下#4。出于性能原因,默认情况下 DB2 for i 将缓存 20 个标识值以供进程使用。因此,如果您有两个进程添加记录,一个将获得 1-20 的值,另一个将获得 20-40。这允许两个进程同时插入。但是,如果进程 1 仅插入 10 条记录,则标识值 11-20 将丢失。如果您绝对必须有连续的标识值,请在创建标识时指定 NO CACHE

      create table test
       myid int generated always 
          as identity 
          (start with 1, increment by 1, no cache)
      

      最后,关于身份值的缓存。在确认此答案的一些事项时,我注意到使用 ALTER TABLE 添加新列似乎会导致缓存值丢失。我插入了 3 行,alter table 和下一行的标识值为 21。

      【讨论】: