尝试批量插入具有自动生成 ID 的对象时出现 NonUniqueObjectException
NonUniqueObjectException when trying to batch insert Objects with Auto-Generated ID
我正在尝试批量插入 List
个对象。我将 ID 配置为自动生成。以前我有以下内容:
<id name="entryId" type="integer" column="ENTRY_ID">
<generator class="seqhilo">
<param name="sequence">HB_ENTRY_ID_SEQ</param>
<param name="max_lo">50</param>
</generator>
</id>
我的插入查询如下:
try (Session session = sessionFactory.openSession()) {
session.beginTransaction();
for (int i = 0; i < insertList.size(); i++) {
session.save(insertList.get(i));
if (i % 100 == 0) {
session.flush();
session.clear();
}
}
session.getTransaction().commit();
return insertList.size();
}
我也设置了正确的 batch_size
属性 值。上面的工作正常,但是,最近我将代码更改为基于注释,并且我有以下内容:
@Id
@Column(name = "ENTRY_ID")
@GeneratedValue(generator = "hibSeq", strategy = GenerationType.SEQUENCE)
@SequenceGenerator(name = "hibSeq", sequenceName = "HB_ENTRY_ID_SEQ", allocationSize = 100)
当我现在运行这个时候,插入抛出一个org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session
我一直在尝试根据 here and here 理解此错误,但未能解决我的问题。据我所知,在 session.flush()/clear()
阶段发生了一些事情,导致序列生成器回收已经使用过的 ID。
我做错了什么?
XML中提供的生成器与注释指定的生成器不同。前者是一个sequence hilo,它会根据一个sequence返回的值生成一个ID前缀。
后者采用序列的值:它将该值和下一个 100 保存在内存中(根据 allocationSize
),这使您可以避免进行 100 次调用。但是,在生成 100 个 ID 后,它将调用 nextval 并生成与第二个条目相同的 ID:
Generated ID 0 (query) .NEXTVAL
Generated ID 1 (in memory)
Generated ID 2 (in memory)
...
Generated ID 100 (in memory)
Generated ID 1 (query) .NEXTVAL
这里的解决方法是ALTER SEQUENCE HB_ENTRY_ID_SEQ INCREMENT BY 100
我正在尝试批量插入 List
个对象。我将 ID 配置为自动生成。以前我有以下内容:
<id name="entryId" type="integer" column="ENTRY_ID">
<generator class="seqhilo">
<param name="sequence">HB_ENTRY_ID_SEQ</param>
<param name="max_lo">50</param>
</generator>
</id>
我的插入查询如下:
try (Session session = sessionFactory.openSession()) {
session.beginTransaction();
for (int i = 0; i < insertList.size(); i++) {
session.save(insertList.get(i));
if (i % 100 == 0) {
session.flush();
session.clear();
}
}
session.getTransaction().commit();
return insertList.size();
}
我也设置了正确的 batch_size
属性 值。上面的工作正常,但是,最近我将代码更改为基于注释,并且我有以下内容:
@Id
@Column(name = "ENTRY_ID")
@GeneratedValue(generator = "hibSeq", strategy = GenerationType.SEQUENCE)
@SequenceGenerator(name = "hibSeq", sequenceName = "HB_ENTRY_ID_SEQ", allocationSize = 100)
当我现在运行这个时候,插入抛出一个org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session
我一直在尝试根据 here and here 理解此错误,但未能解决我的问题。据我所知,在 session.flush()/clear()
阶段发生了一些事情,导致序列生成器回收已经使用过的 ID。
我做错了什么?
XML中提供的生成器与注释指定的生成器不同。前者是一个sequence hilo,它会根据一个sequence返回的值生成一个ID前缀。
后者采用序列的值:它将该值和下一个 100 保存在内存中(根据 allocationSize
),这使您可以避免进行 100 次调用。但是,在生成 100 个 ID 后,它将调用 nextval 并生成与第二个条目相同的 ID:
Generated ID 0 (query) .NEXTVAL
Generated ID 1 (in memory)
Generated ID 2 (in memory)
...
Generated ID 100 (in memory)
Generated ID 1 (query) .NEXTVAL
这里的解决方法是ALTER SEQUENCE HB_ENTRY_ID_SEQ INCREMENT BY 100