Hibernate 批量保存嵌套对象
Hibernate Batch Save Nested Objects
我有以下 class 结构:
class A{
int id;
List<B> blist;
List<C> clist;
List<D> dlist;
}
我得到一个 json 作为输入,它被映射器映射到对象 A。现在,我有对象 A,其中包含 B、C 和 D 对象的列表。我想使用批处理来节省插入时间。如果我想保存多个父对象,我通过了描述解决方案的 documentation。在我的情况下,我将如何使用批处理功能,它具有多种类型的嵌套对象列表。
我使用
启用了批量插入
<property name="hibernate.jdbc.batch_size">50</property>
这本身不会给我任何批处理,除非我清除并刷新会话。关于如何处理这个问题有什么建议吗?
问题是您正在使用 IDENTITY
策略。
每当您保存一个新实体时,Hibernate 都会将其放入 Session 的 1LC;然而,为了做到这一点,标识符必须是已知的。 IDENTITY
策略的问题在于 Hibernate 必须实际执行插入以确定标识符值。
最后,批量插入功能被禁用了。
您应该尝试使用预先已知的业务键值加载数据,或者更糟的情况是使用带有序列优化器的 SEQUENCE
生成类型来最小化数据库命中。这将允许批量插入工作。
更新
对于没有定义行唯一性的业务键并且数据库没有 SEQUENCE
支持的情况,您可以自己管理标识符。您可以选择使用自定义标识符生成器来执行此操作,也可以选择在循环中作为代码执行此操作。
这里需要注意的是这个解决方案不是线程安全的。您应该保证在任何时候都不会 运行 在两个线程中同时执行此逻辑,这通常不是一个人在批量数据加载时所做的事情。
定义一个变量来存储你的标识符。我们需要根据数据库中标识符的现有最大值来初始化这个变量。如果数据库中不存在任何行,我们可能希望将其初始化为 1。
Long value = ... // createQuery ( "SELECT MAX(id) FROM YourEntity" )
value = ( value == null ? 1L : value + 1);
下一步是更改 @Id
注释字段。它不应标记为 @GeneratedValue
,因为我们将允许应用程序提供该值。
对于您要插入的每一行,只需使用步骤 1 中生成的值变量调用您的 #setId( value )
方法。
将您的 value
变量增加 1。
我有以下 class 结构:
class A{
int id;
List<B> blist;
List<C> clist;
List<D> dlist;
}
我得到一个 json 作为输入,它被映射器映射到对象 A。现在,我有对象 A,其中包含 B、C 和 D 对象的列表。我想使用批处理来节省插入时间。如果我想保存多个父对象,我通过了描述解决方案的 documentation。在我的情况下,我将如何使用批处理功能,它具有多种类型的嵌套对象列表。
我使用
启用了批量插入<property name="hibernate.jdbc.batch_size">50</property>
这本身不会给我任何批处理,除非我清除并刷新会话。关于如何处理这个问题有什么建议吗?
问题是您正在使用 IDENTITY
策略。
每当您保存一个新实体时,Hibernate 都会将其放入 Session 的 1LC;然而,为了做到这一点,标识符必须是已知的。 IDENTITY
策略的问题在于 Hibernate 必须实际执行插入以确定标识符值。
最后,批量插入功能被禁用了。
您应该尝试使用预先已知的业务键值加载数据,或者更糟的情况是使用带有序列优化器的 SEQUENCE
生成类型来最小化数据库命中。这将允许批量插入工作。
更新
对于没有定义行唯一性的业务键并且数据库没有 SEQUENCE
支持的情况,您可以自己管理标识符。您可以选择使用自定义标识符生成器来执行此操作,也可以选择在循环中作为代码执行此操作。
这里需要注意的是这个解决方案不是线程安全的。您应该保证在任何时候都不会 运行 在两个线程中同时执行此逻辑,这通常不是一个人在批量数据加载时所做的事情。
定义一个变量来存储你的标识符。我们需要根据数据库中标识符的现有最大值来初始化这个变量。如果数据库中不存在任何行,我们可能希望将其初始化为 1。
Long value = ... // createQuery ( "SELECT MAX(id) FROM YourEntity" ) value = ( value == null ? 1L : value + 1);
下一步是更改
@Id
注释字段。它不应标记为@GeneratedValue
,因为我们将允许应用程序提供该值。对于您要插入的每一行,只需使用步骤 1 中生成的值变量调用您的
#setId( value )
方法。将您的
value
变量增加 1。