Spring JPA-序列缓存提供了意外的行为。使用分配大小= 1可以

时间:2019-02-20 12:29:31

标签: java jpa spring-data-jpa sequence id-generation

我的Spring Boot应用程序使用a.o。 2实体类。实体类别1使用的技术密钥ID使用序列。实体包含其他实体的列表,因此是一对多的。子实体使用相同的序列。

使用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)

等等

1 个答案:

答案 0 :(得分:1)

将JPA与DB序列结合使用时要当心。一个解决方案使用的分配大小为1。我同时使用Oracle和Progress进行了测试。

您可以通过this post找到很好的解释。 Puspender Tanwar ,给出了详尽的解释!

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

  

创建序列“ APPS”。“ LINE_LOCQTY_JPA_ID_SQ” MINVALUE 1 MAXVALUE   999999999999999999999999999从20开始以7641缓存20递增   NOORDER NOCYCLE;

前一个Sequence(IncrementBy值为1)的问题的说明:

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

INCREMENTBY 20如何解决此问题:当在第3步消耗Ids时,JPA要求Sequence的下一个值。上次返回的值是7641,因此这一次它将增加20,并返回7661。JPA创建从7661到7680的值并使用它们。因此,不存在唯一的密钥冲突问题。