使用JPA + Hibernate进行大规模插入

我需要使用EJB 3,Hibernate,Spring Data和Oracle进行大量插入。 最初,我使用的是Spring Data,代码如下:

talaoAITDAO.save(taloes); 

其中talaoAITDAO是Spring Data JpaRepository子类,taloes是TalaoAIT实体的集合。 在此实体中,其各自的ID具有以下forms:

 @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批量大小的混乱和其他页面 。 基于它们,我写了这段代码:

 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(); 

另外,在peristence.xml中,我添加了以下属性:

   

然而,虽然在我的测试中我发现了一个微妙的差异(主要是大集合和大批量),但它并没有那么大。 在日志控制台中,我看到Hibernate继续进行单独插入,而不是替换它们进行大量插入。 在我的实体中,我使用的是序列生成器我相信它不是问题(根据Hibernate文档,如果我使用Identity生成器,我会遇到问题)。

所以,我的问题是这里可以缺少什么。 一些配置? 有些方法没用过?

谢谢,

拉斐尔阿丰索。

有几件事。

首先你的配置属性是错误的order_inserts必须是hibernate.order_inserts 。 目前您的设置被忽略,您没有更改任何内容。

接下来使用EntityManager而不是做所有讨厌的hibernate东西。 EntityManager还具有flushclear方法。 这至少应该清理你的方法。 如果没有这个顺序,这有助于清理会话并防止对那里的所有对象进行脏检查。

 EntityManager em = getEntityManager(); int batchSize = 1000; for (int i = 0; i < taloes.size(); i++) { TalaoAIT talaoAIT = taloes.get(i); em.persist(talaoAIT); if(i % batchSize == 0) { em.flush(); em.clear(); } taloes.add(talaoAIT); } em.flush(); em.clear(); 

接下来你不应该让你的批次变大,因为这可能会导致内存问题,从50开始,测试哪些/什么表现最佳。 有一点,脏检查将花费更多时间,然后刷新并清除到数据库。 你想找到这个甜蜜点。

M. Deinum发布的解决方案非常适合我,前提是我在JPA persistence.xml文件中设置了以下Hibernate属性:

       

我正在使用Oracle数据库,所以我也定义了这个:

  

我最近发现了一个很有前途的小库,用于使用Hibernate和Postgresql批量插入。 它被称为踏板方言并使用Postgresql – 命令COPY ,许多人声称它比批量插入快得多(参考: Postgresql手册 , Postgresql插入策略 – 性能测试 , 如何复制工作,为什么它更快比插入? )。 踏板方言允许使用COPY而不会完全失去Hibernate的易用性。 您仍然可以自动映射实体和行,而不必自己实现它。