在JPA中插入多行的最有效方法

ven*_*syv 6 java mysql hibernate jpa-2.0

我有父/子单向关系.当我检查日志时,我看到每个子行都有一个单独的插入查询,相当于让我们说:

insert into childTable(col1, col2) values(val1, val2);
insert into childTable(col1, col2) values(val3, val4);
Run Code Online (Sandbox Code Playgroud)

在单个查询中插入所有行不是更有效吗?有点像:

insert into childTable(col1, col2) values(val1, val2), (val3, val4)
Run Code Online (Sandbox Code Playgroud)

有没有办法强制JPA生成多行插入而不是单行插入?

编辑: 我目前正在使用级联插入,所以我插入父级,并自动生成子项的插入.我宁愿继续使用该方法,而不是让我们说手动创建一个巨大的SQL查询,因为我认为级联插入产生更清晰的代码.

我已经定期刷新会话以控制L1缓存的大小,因此耗尽内存不是问题.

Rob*_*Rob 5

在单个查询中插入所有行实际上效率较低。

首先,有几点观察:

  1. 从客户端传递到服务器的数据量与一个或多个插入语句相同,其中“数据量”表示您正在存储的实际值。
  2. Hibernate 支持批量请求,因此客户端和服务器之间的往返次数可以与一个或多个插入语句大致相同。

在幕后,HibernatePreparedStatement为它代表您执行的每个查询使用一个 ,并且这些查询被缓存和重用。MySQL 会缓存“编译”的 SQL 语句。在不陷入细节的情况下,底层技术经过高度优化,可以多次运行相对少量的查询。

如果您将插入作为单个语句进行,则每次要插入的值的数量不同时,都必须编译和缓存新的 SQL(可能会从缓存中推送另一个查询),这会增加开销。如果每次都使用相同的 SQL,则可以避免这种开销。

由于多种原因,您必须在 SQL 中使用绑定变量,Hibernate 会自动为您执行此操作。如果您执行一些自定义查询来测试一次性插入方法,那么您绝对应该使用绑定变量。

另一个考虑因素是如何生成标识符。如果是通过数据库中的标识列,那么 Hibernate 需要接收每列的 ID,这通常只有在创建一行时才可能实现。因此,为了提高效率,基于序列的标识符生成器是首选,并具有序列值的客户端缓存。

我刚刚注意到您的编辑:我的经验是 Hibernate 在处理插入父子数据时会进行“额外”更新。尽管我只有多对一关系,但我设法通过将映射更改为具有“联接”表(就像您在多对多关系中看到的那样)来获得“纯”插入。就我而言,对三个表进行更多的插入与对两个表进行更少的插入和更新要快得多。如果您关心性能,您绝对应该计划一些时间来调整 Hibernate 配置。

  • @ventsyv & Rob 我知道我迟到了,但请检查[这个](http://stackoverflow.com/a/1793209/1398531) (2认同)