javax.persistence.EntityExistsException 与 SequenceGenerator

标签 java oracle hibernate jpa-2.0

我正在 Oracle DB 中插入一些记录。为了独特性,我使用 SequenceGenerator。下面是代码:

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 与 XxspPoInLine 具有 @ManyToOne 关系。当我保留 XxspPoInLine 实体时,我收到以下错误:

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)

我查看了 stackoverflow,找到了一些解决方案: 1.使用allocationSize=1 由于我有 5000+ XxspPoInLineLocqty ,这将是我可以应用的最糟糕的选择。我也尝试过这个,但 40 分钟后我的网络出现波动,持久化失败了。我无法使用此选项,因为它会降低性能。

<强>2。增加分配大小的值 我增加了 allocateSize=500,但在不同的标识符上仍然面临相同的问题(#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)

甚至尝试过GenerationType.AUTO,但没有运气。 以下是 Oracle DB 上的序列:

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

我仍然很困惑为什么会出现这个问题。我不明白这的根本原因。有人可以向我解释一下这个异常的根本原因,以及应该采取什么解决办法吗?

注意:在插入记录之前,我删除了表中的所有行。所以当我执行上面的序列代码时,表格是空白的。

最佳答案

allocationSize 参数必须与序列的 INCRMENT BY 值匹配。

它的工作方式是,Hibernate 从序列(从数据库)中获取一个值,然后将该值保留在内存中,并生成下一个 X 个后续标识符(其中 X=allocationSize),并在该值中将该值增加 1。内存,无需访问数据库。

一旦 Hibernate 生成 X 标识符,它就会从序列中获取下一个值,并生成新的 X 标识符,将该值增加 1

<小时/>

一个简单的例子 - 让我们这样说:

  • @SequenceGenerator( ....allocationSize=5 ...)
  • 创建序列 .... 递增 1 ...

在上述情况下 hibernate :

  1. 从序列中获取第一个数字 - 比如说 NextVal = 1 并将其存储在内存中
  2. 生成下一个 allocationSize=5 标识符,并将上述值加 1,即:Id = 1, 2, 3, 4, 5
  3. 从序列中获取下一个数字 - 由于 INCRMENT BY 1nextVal 将是:2
  4. 生成下一个 allocationSize=5 标识符,并将上述值加 1,即:Id = 2, 3, 4, 5, 6

如您所见,这会导致重复错误。

<小时/>

现在请考虑这种情况:

  • @SequenceGenerator( ....allocationSize=5 ...)
  • 创建序列 .... 递增 5 ...

在本例中为 hibernate :

  1. 从序列中获取第一个数字 - 比如说 NextVal = 1 并将其存储在内存中
  2. 生成下一个 allocationSize=5 标识符,并将上述值加 1,即:Id = 1, 2, 3, 4, 5
  3. 从序列中获取下一个数字 - 由于 INCRMENT BY 5nextVal 将是:6
  4. 生成下一个 allocationSize=5 标识符,并将上述值递增 1,即:Id = 6, 7, 8, 9, 10

在本例中不存在重复错误。

<小时/>

最后一种情况的缺点是,如果序列在 Hibernate 之外使用,那么序列将产生间隙。

关于javax.persistence.EntityExistsException 与 SequenceGenerator,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48020829/

相关文章:

java - 注解@NotEmpty不检查String是否为null

java - Scene2d 在 table 顶部添加 Actor

java - Hibernate 无法解析嵌入类的属性

java - 使用 Jersey + hibernate RESTful web 服务上传和下载图像

java - 在 Ant 中为 jUnit 任务设置编码

java - 右键单击 Sonar 选项不可用

java - Oracle DB 表或 View 不存在

java - ORA-56721 : I/O data limit exceeded - session terminated

java - 如何通过 Java 更快地执行 Oracle 更新/插入操作?

java - 如何在 Hibernate 中内连接两个独立实体