javax.persistence.EntityExistsException with SequenceGenerator

跟風遠走 提交于 2019-12-04 04:59:30

问题


I am inserting some records in Oracle DB. For the uniqueness, I am using SequenceGenerator. Below is the code:

public class XxspPoInLineLocqty implements Serializable {
    @Id 
    @SequenceGenerator(name = "SequenceLocIdGenerator", sequenceName = "LINE_LOCQTY_JPA_ID_SQ")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SequenceLocIdGenerator")
    @Column(name="LINE_LOCQTY_JPA_ID")
    private Long lineLocqtyJPAId;

//other fields..
}

XxspPoInLineLocqty is having @ManyToOne relation with XxspPoInLine. When I am persisting XxspPoInLine entity, I am receiving below error:

javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [com.bcone.oracle.ebs.model.XxspPoInLineLocqty#76]
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:116)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:162)
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:804)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:764)
    at org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1.cascade(JpaPersistEventListener.java:80)
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:391)

I looked on the stackoverflow and found some solutions for this: 1. Use allocationSize=1 Since I am having 5000+ XxspPoInLineLocqty , this would be the worst option I could apply. I tried this as well but after 40min my network got fluctuate and persisting got failed. I cannot use this option as it degrade the performance.

2. Increse the value of allocation size I increased the allocationSize=500, but still faced the same issue at different identifier(#372).

javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [com.bcone.oracle.ebs.model.XxspPoInLineLocqty#-372]
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:116)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:162)
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:804)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:764)
    at org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1.cascade(JpaPersistEventListener.java:80)
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:391)
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:316)

Even tried GenerationType.AUTO, but no luck. Below is the sequence on Oracle DB:

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

I am still confused why this issue is coming up. I didn't understand the root cause of this. Can someone explain me the root cause of this exception, and what should be the work around?

Note : Before inserting the records, I deleted all the rows from table. So the table is blank when I execute the above sequnce code.


回答1:


allocationSize parameter must match the INCREMENT BY value of the sequence.

It works in such a way that Hibernate gets a value from the sequence (from the database), and then keeps that value in the memory and generates next X subsequent identifiers (where X=allocationSize) incrementing this value by 1 in the memory, without reaching for the database.

Once Hibernate generates X identifiers, it gets the next value from the sequence, and generates new X identifiers, incrementing that value by 1


A simple example - let say that:

  • @SequenceGenerator( ....allocationSize=5 ...)
  • CREATE SEQUENCE .... INCREMENT BY 1 ...

In the above case Hibernate:

  1. Fetches the first number from the sequence - let say NextVal = 1 and stores it in the memory
  2. Generates next allocationSize=5 identifiers incrementing the above value by 1, that is: Id = 1, 2, 3, 4, 5
  3. Fetches the next number from the sequence - because of INCREMENT BY 1, the nextVal will be: 2
  4. Generates next allocationSize=5 identifiers incrementing the above value by 1, that is: Id = 2, 3, 4, 5, 6

As you can see, it will cause a dulicate error.


Now please consider this case:

  • @SequenceGenerator( ....allocationSize=5 ...)
  • CREATE SEQUENCE .... INCREMENT BY 5 ...

In this case Hibernate:

  1. Fetches the first number from the sequence - let say NextVal = 1 and stores it in the memory
  2. Generates next allocationSize=5 identifiers incrementing the above value by 1, that is: Id = 1, 2, 3, 4, 5
  3. Fetches the next number from the sequence - because of INCREMENT BY 5, the nextVal will be: 6
  4. Generates next allocationSize=5 identifiers incrementing the above value by 1, that is: Id = 6, 7, 8, 9, 10

In this case there is no duplicate error.


The last case has the disadvantage that if the sequence is used outside of Hibernate, then the sequence will produce gaps.



来源:https://stackoverflow.com/questions/48020829/javax-persistence-entityexistsexception-with-sequencegenerator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!