使用 JPA EntityManager 进行批量插入
Posted
技术标签:
【中文标题】使用 JPA EntityManager 进行批量插入【英文标题】:Batch inserts using JPA EntityManager 【发布时间】:2012-05-21 23:42:01 【问题描述】:有没有一种方法可以让我们使用 JPA EntityManager 来使用批量插入。我知道没有直接的方法可以实现这一点,但必须有某种方法可以实现这种机制。
实际上,对于每个插入操作,我需要 300 毫秒,我想使用批量插入而不是单次插入来减少。
这是我当前正在为单个插入执行的代码
@PersistenceContext(unitName = "testing")
EntityManager eM;
Query querys = this.eM.createNativeQuery(insertQuery);
for (String s : someList)
//setting parameters
querys.executeUpdate();
提前致谢。
【问题讨论】:
【参考方案1】:根据事务是否包含循环,批处理通常已经在您的情况下发生。
JPA 将在其 L1 缓存中收集您的所有更新,并通常在事务提交时将所有更新批量写入数据库。这与 JDBC 中的批处理并没有什么不同,您添加的每个批处理项也暂时在内存中,直到您调用更新方法。
潜在的问题是,您没有硬性保证 JPA 确实会执行此批处理,以及是否在事务提交或达到阈值时执行此操作,但我发现在实践中几乎在所有情况下,尤其是在某些情况下涉及这样一个简单的更新循环,它确实可以进行批处理。
一个问题是,即使 JPA 确实已经进行了批处理,您仍然可能希望控制批处理大小。其他答案链接的文章为此提供了非常有用的信息。
最后,你应该知道你的 L1 缓存一直在循环增长,所以如果更新的数量真的很大,请定期清除它。或者,如果您的业务逻辑可以维持它,请在多个事务中进行部分更新。例如。事务 1 中的项目 0 到 100.000,事务 2 中的 100.001 到 200.000 等。
【讨论】:
嘿,我现在用的是spring data jpa,所以你的意思是如果我在一个方法内循环更新对象并且这个方法被@Transactional标记,它会像jdbc批量更新一样自动批量更新。跨度> 【参考方案2】:我知道这是一个相当古老的问题,但答案已被接受。尽管如此,我想对这个非常具体的主题“JPA 批量插入”给出一个新的答案。
@PersistenceContext
private EntityManager entityManager;
@Value("$hibernate.jdbc.batch_size")
private int batchSize;
public <T extends MyClass> Collection<T> bulkSave(Collection<T> entities)
final List<T> savedEntities = new ArrayList<T>(entities.size());
int i = 0;
for (T t : entities)
savedEntities.add(persistOrMerge(t));
i++;
if (i % batchSize == 0)
// Flush a batch of inserts and release memory.
entityManager.flush();
entityManager.clear();
return savedEntities;
private <T extends MyClass> T persistOrMerge(T t)
if (t.getId() == null)
entityManager.persist(t);
return t;
else
return entityManager.merge(t);
来源:http://frightanic.com/software-development/jpa-batch-inserts/
【讨论】:
我想我们需要在最后再次flush()
和 clear()
来保存任何未完成我们批量大小的剩余对象?【参考方案3】:
可以使用 JPA 执行批量写入,但它高度依赖于持久性提供程序、数据库和 JDBC 驱动程序的具体实现。例如,article 解释了如何使用 EclipseLink JPA 2.3 和 Oracle 数据库启用批量写入(优化 #8)。在您的特定环境中寻找类似的配置参数。
【讨论】:
嗨,你能给我一些代码sn-p如何在上面提供的代码中使用它。 @Rana 如上所述:这取决于您使用的持久性提供程序 - 我无法通过查看代码来判断,您必须告诉我。 嗨,我正在使用 org.eclipse.persistence.jpa.PersistenceProvider。如果使用批量插入有任何限制,请告诉我。 @Rana 都在链接的文章中,您必须编辑persistence.xml
文件并添加类似<property name="eclipselink.jdbc.batch-writing" value="JDBC"/> <property name="eclipselink.jdbc.batch-writing.size" value="1000"/>
的内容。请花时间先阅读文章。
嗨,我已经添加了这一点,并且我正在寻找我需要使用此语句观察的任何陷阱的信息。谢谢。【参考方案4】:
JPA 本身没有任何批处理设置。但是,有一些依赖于实现的设置。 Here is an example for hibernate.
【讨论】:
看我的例子here以上是关于使用 JPA EntityManager 进行批量插入的主要内容,如果未能解决你的问题,请参考以下文章