我需要使用 EJB 3、Hibernate、Spring Data 和 Oracle 进行大规模插入。最初,我正在使用 Spring Data,以下是代码:
talaoAITDAO.save(taloes);
talaoAITDAO是Spring Data的JpaRepository子类,而taloes是TalaoAIT实体的集合。在该实体中,其相应的ID具有以下形式:
@Id
@Column(name = "ID_TALAO_AIT")
@SequenceGenerator(name = "SQ_TALAO_AIT", sequenceName = "SQ_TALAO_AIT", allocationSize = 1000)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SQ_TALAO_AIT")
private Long id;
此实体没有相关的实体可以进行级联插入。
我的问题在于所有实体都是单独插入的(例如INSERT INTO TABLE (col1,col2) VALUES (val1,val2)
)。偶尔会导致超时并且所有插入都将回滚。我希望将这些单独的插入转换成批量插入(例如INSERT INTO TABLE(col1, col2) VALUES (val11, val12), (val21, val22), (val31, val32), ...
)。
为了改善性能,我研究了一些替代方案,并找到了hibernate文档中的这个页面,以及Hibernate batch size confusion和这另一个页面。基于它们,我编写了这段代码:
Session session = super.getEntityManager().unwrap(Session.class);
int batchSize = 1000;
for (int i = 0; i < taloes.size(); i++) {
TalaoAIT talaoAIT = taloes.get(i);
session.save(talaoAIT);
if(i % batchSize == 0) {
session.flush();
session.clear();
}
taloes.add(talaoAIT);
}
session.flush();
session.clear();
另外,在 persistence.xml 文件中,我添加了以下这些属性:
<property name="hibernate.jdbc.batch_size" value="1000" />
<property name="order_inserts" value="true" />
然而,尽管在我的测试中我感觉到了微妙的差异(主要是在大集合和大批量大小方面),但它并不像期望的那样大。在日志控制台中,我看到Hibernate继续执行单个插入操作,而不是替换它们进行大规模插入。由于在我的实体中,我使用了Sequence生成器,我相信这不是问题(根据Hibernate文档,如果我使用Identity生成器,我会遇到问题)。
所以,我的问题是这里可能缺少什么。一些配置?一些未使用的方法?
谢谢,
Rafael Afonso。
session
?你可以直接在entityManager
上执行flush()
和clear()
。但是通常使用 Java 进行大量插入是错误的方式;将所有内容转储到文件中,将其传输到目标服务器并进行批量加载通常效果更好。话虽如此,偶尔你确实需要在代码中进行一些转换;这也许就是其中之一。 - beerbajay