在单个事务中插入多个实体 | Hibernate,JPA

huangapple go评论73阅读模式
英文:

INSERT multiple entities in a single transaction | Hibernate, JPA

问题

我正在尝试创建一个POST端点,使用Spring MVC,负责创建多个实体对象。

在服务层,代码大致如下:

entities.forEach(entity -> entityManager.persist(entity))

这将在一个单元的工作中完成,还是行将逐一插入?

英文:

I'm trying to create a POST endpoint, using spring MVC, that is responsible for creating multiple entity objects.

At the service layer, the code looks something like this

entities.forEach(entity -> entityManager.persist(entity))

Will this be done in a single unit of work, or the rows will be inserted one by one?

答案1

得分: 1

插入操作将始终逐一进行,Hibernate 将以这种方式处理它们。然而,您可以启用 JDBC 批量插入,这可能需要对插入语句进行一些重新排序,例如,当依赖实体也需要插入时。

举个例子,如果 A 对象引用了 B 对象,并且您想要插入 A1 和 B1,以及 A2 和 B2,那么 Hibernate 将不得不将其重新排序为 A1、A2、B1、B2(或更可能是 B1、B2、A1、A2 如果 A 有外键的话)- 这是您需要启用的功能。

请注意,要使用批处理,一切都必须在同一个事务中运行,也就是您已发布的代码行必须在 JTA 事务或 Hibernate 会话上下文中运行。

Hibernate 5.4.20 文档链接:https://docs.jboss.org/hibernate/stable/orm/userguide/html_single/Hibernate_User_Guide.html#batch

但是需要注意以下几点:

  • 让 Hibernate 记录 SQL 语句可能会给人一种没有批处理发生的印象,但那只是一个日志问题。
  • 如果您的服务打算在一个事务中创建大量实体,您可能需要采取一些额外的步骤,以防止脏检查等对性能产生负面影响(例如,在插入 X 个实体后分割批次并清除一级缓存 - 理想情况下,X 将是 JDBC 批量大小)。
英文:

Well, inserts will always be one by one and Hibernate will process them that way. However, you can enable JDBC batch inserts which might require some reordering of the insert statements, e.g. when dependent entities need to be inserted as well.

As an example, if A has a reference to B and you want to insert A1 and B1 as well as A2 and B2 then Hibernate would have to reorder that to A1, A2, B1, B2 (or more likely B1, B2, A1, A2 if A has the foreign key) - which is something you'd need to enable.

Note that to use batching everything would have to run in the same transaction, i.e. the line you've posted would have to run in a JTA transaction or Hibernate session context.

Documentation for Hibernate 5.4.20: https://docs.jboss.org/hibernate/stable/orm/userguide/html_single/Hibernate_User_Guide.html#batch

A few notes though:

  • Having Hibernate log the SQL statements might give the impression that no batching occurs but that's just a logging issue.
  • If your service is going to create a large number of entities in one transaction you might want to take some extra steps to prevent dirty checks etc. having a negative effect on performance (e.g. by splitting the batch and clearing first level cache after inserting X entities - ideally X would be the JDBC batch size).

huangapple
  • 本文由 发表于 2020年8月15日 04:49:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/63419852.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定