当前位置: 首页 > 面试题库 >

具有SequenceGenerator的javax.persistence.EntityExistsException

宋昊然
2023-03-14
问题内容

我正在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. 增加 分配大小的值 我增加了allocationSize = 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参数必须与INCREMENT BY序列的值匹配。

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

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

一个简单的例子-假设:

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

在上述情况下,Hibernate:

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

如您所见,它将导致双重错误。

现在请考虑这种情况:

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

在这种情况下,hibernate:

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

在这种情况下,没有重复的错误。

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



 类似资料:
  • 我有一个使用JPA注释生成数据库主键的代码。一个数据库序列用于使用Oracle DB生成PK.Am 现在我对此的理解是:DB sequencer返回的sequence id作为rec_id。这是正确的吗? 医生说: 序列策略序列策略由两部分组成——定义命名序列和在一个或多个类的一个或多个字段中使用命名序列。@Sequence Generator注释用于定义序列并接受名称、初始值(默认值为1)和分配

  • 问题内容: 我们都知道使用Hibernate时的默认行为-它使实际数据库序列增加 一 ,将该值乘以50(默认值)-然后将该值用作实体ID。 这是错误的行为,并与说明以下内容的规范冲突: distributionSize-(可选)从序列中分配序列号时要增加的数量。 需要明确的是:我不关心生成的ID之间的差距。 我关心与基础数据库序列 不一致的 ID 。例如:任何其他应用程序(例如,使用纯JDBC)可

  • 问题内容: 我将JPA2与Hibernate结合使用,并尝试为我的实体引入一个通用的基类。到目前为止看起来像这样: 但是,对于每个表,都有一个序列要用作序列生成器。我该如何在子类中进行设置?我想我需要重写@GeneratedValue并使用@SequenceGenerator创建一个新的SequenceGenerator。 问题答案: 是的,有可能。您可以使用注释覆盖默认的生成器名称。 基类 序列

  • 问题内容: 我的实体具有以下结构: 我得到以下异常: 当我在Intermed类上将@MappedSuperclass更改为@Entity时,一切正常。使用@MappedSuperclass和@SequenceGenerator是否有任何问题?还是我错过了什么? 问题答案: 这是JPA 1.0规范对注释的说明: 9.1.37 SequenceGenerator批注 该注解定义了可以由名称当用于指定的

  • 问题内容: 我有一个问题: 当应用程序启动时,它显示警告: WARN 7388 — [main] org.hibernate.orm.deprecation:HHH90000014:发现使用不推荐使用的[org.hibernate.id.SequenceHiLoGenerator]基于序列的id生成器;请改用org.hibernate.id.enhanced.SequenceStyleGenera

  • 我对有问题: 应用程序启动时会显示警告: 警告7388---[main]组织。冬眠orm。弃用:HH90000014:发现使用弃用的[org.hibernate.id.SequenceHiLoGenerator]基于序列的id生成器;使用组织。冬眠id.enhanced。相反,SequenceStyleGenerator。有关详细信息,请参阅《Hibernate域模型映射指南》 我试图找出如何用新