1

我的 Spring Boot 应用程序使用 2 个实体类。实体类 1 使用使用序列的技术密钥 id。实体包含其他实体的列表,因此是一对多的。Child 实体使用相同的序列。

使用 20 的序列分配(缓存)大小,我看到我得到 EntityExistsException:

javax.persistence.EntityExistsException:具有相同标识符值的不同对象已与会话关联:[nl.xyz.app1.entity.ChildFields #123456]

实体是:

@Entity
@Table(name = "CHILD_FIELDS")
public class ChildFields implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "my_entity_seq_gen")
    @SequenceGenerator(name = "my_entity_seq_gen", sequenceName = "MYSEQ_S01")
    @Column(name = "CF_ID", unique = true, nullable = false)
    private Long id;

    @Column(name = "CF_DETAILS_ID")
    private Long detailsId;

@Entity
@Table(name = "PARENTS_OBJECT")
public class ParentObject implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "my_entity_seq_gen")
    @SequenceGenerator(name = "my_entity_seq_gen", sequenceName = "MYSEQ_S01")
    @Column(name = "PF_ID", unique = true, nullable = false)
    private Long id;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "CF_DETAILS_ID")
    private List<ChildFields> children;

当我使用分配序列 1 时,一切正常!为什么是这样?

@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "my_entity_seq_gen" )
@SequenceGenerator(name = "my_entity_seq_gen", sequenceName = "MYSEQ_S01", allocationSize=1)

等等。

4

1 回答 1

2

将 JPA 与 DB 序列结合使用时要小心。一个解决方案是使用 1 的 allocationSize。我用 Oracle 和 Progress 测试了这个。

你可以通过这篇文章找到一个很好的解释。Puspender Tanwar,给出了详尽的解释!

通过将 Sequence IncrementBy 值更改为我在 JPA 的 allocationSize 中设置的值来解决该问题。

CREATE SEQUENCE "APPS"."LINE_LOCQTY_JPA_ID_SQ" MINVALUE 1 MAXVALUE 999999999999999999999999999 INCREMENT BY 20 START WITH 7641 CACHE 20 NOORDER NOCYCLE ;

上一个Sequence(IncrementBy value 1)问题的解释:

  1. 当 JPA 需要 Id 值时,它会点击 DB Sequence 并要求唯一值,Sequence 返回 7641。
  2. 现在 JPA 有了 ID 的起点,基于 allocationSize=20,JPA 自己创建接下来的 20 个值并生成 7641 到 7660 个唯一 ID。
  3. 现在,当所有这些 ID 都被使用时,JPA 向 DB Sequence 询问下一个唯一值。并且由于返回的最后一个值为 7641,因此序列返回 7642(因为 INCREMENTBY 值为 1 )。
  4. JPA 获取 7642 并在缓存中创建接下来的 20 个值。
  5. 当 JPA 尝试将这些值分配给 ID 时,它发现 7642 已分配给实体对象(在步骤 2)。

INCREMENTBY 20 如何解决该问题:当 ID 在第 3 步被消耗时,JPA 向 Sequence 请求下一个值。最后一个返回值是 7641,所以这次它将增加 20 并返回 7661。JPA 创建从 7661 到 7680 的值并使用它们。因此没有唯一的密钥违规问题。

于 2019-02-23T17:10:23.337 回答