Spring JPA - 序列缓存出现意外行为。使用 allocation size = 1 是可以的
Spring JPA - sequence caching gives unexpected behaviour. Using allocation size = 1 is ok
我的 Spring 启动应用程序使用 a.o。 2 个实体 classes。实体 class 1 使用使用序列的技术密钥 ID。实体包含其他实体的列表,因此是一对多的。 Child 实体使用相同的序列。
使用大小为 20 的序列分配(缓存),我发现我得到了 EntityExistsException:
javax.persistence.EntityExistsException: A different object with the
same identifier value was already associated with the session :
[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)
等
将 JPA 与 DB 序列结合使用时要小心。一个解决方案是使用 allocationSize 为 1。我用 Oracle 和 Progress 测试了这个。
你可以通过this post找到一个很好的解释。 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)问题的解释:
- 当 JPA 需要 Id 值时,它会命中 DB Sequence 并请求唯一值,Sequence returns 7641。
- 现在 JPA 有一个 ID 起点,并且基于 allocationSize=20,JPA 自己创建接下来的 20 个值并生成 7641 到 7660 个唯一 ID。
- 现在,当所有这些 ID 都被使用时,JPA 会向数据库序列询问下一个唯一值。由于最后一个值 returned 是 7641,序列 returns 7642(因为 INCREMENTBY 值是 1 )。
- JPA 获取 7642 并在缓存中创建接下来的 20 个值。
- 当 JPA 尝试将这些值分配给 ID 时,它发现 7642 已经分配给实体对象(在步骤 2)。
INCREMENTBY 20 如何解决这个问题:当 ID 在第 3 步被消耗时,JPA 向 Sequence 请求下一个值。上一个值 return 是 7641,所以这次它将增加 20 和 return 7661。JPA 创建从 7661 到 7680 的值并使用它们。因此不存在唯一的密钥违规问题。
我的 Spring 启动应用程序使用 a.o。 2 个实体 classes。实体 class 1 使用使用序列的技术密钥 ID。实体包含其他实体的列表,因此是一对多的。 Child 实体使用相同的序列。
使用大小为 20 的序列分配(缓存),我发现我得到了 EntityExistsException:
javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [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)
等
将 JPA 与 DB 序列结合使用时要小心。一个解决方案是使用 allocationSize 为 1。我用 Oracle 和 Progress 测试了这个。
你可以通过this post找到一个很好的解释。 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)问题的解释:
- 当 JPA 需要 Id 值时,它会命中 DB Sequence 并请求唯一值,Sequence returns 7641。
- 现在 JPA 有一个 ID 起点,并且基于 allocationSize=20,JPA 自己创建接下来的 20 个值并生成 7641 到 7660 个唯一 ID。
- 现在,当所有这些 ID 都被使用时,JPA 会向数据库序列询问下一个唯一值。由于最后一个值 returned 是 7641,序列 returns 7642(因为 INCREMENTBY 值是 1 )。
- JPA 获取 7642 并在缓存中创建接下来的 20 个值。
- 当 JPA 尝试将这些值分配给 ID 时,它发现 7642 已经分配给实体对象(在步骤 2)。
INCREMENTBY 20 如何解决这个问题:当 ID 在第 3 步被消耗时,JPA 向 Sequence 请求下一个值。上一个值 return 是 7641,所以这次它将增加 20 和 return 7661。JPA 创建从 7661 到 7680 的值并使用它们。因此不存在唯一的密钥违规问题。