使用JPA / EJB3批量插入

JPA / EJB3框架是否提供了批量插入操作的标准方法……? 我们使用hibernate作为持久性框架,所以我可以回退到Hibernate Session并使用组合session.save()/ session.flush()实现批量插入。 但是想知道EJB3是否支持这个……

JPA和Hibernate都没有为批量插入提供特殊支持,而使用JPA批量插入的习惯用法与Hibernate相同:

EntityManager em = ...; EntityTransaction tx = em.getTransaction(); tx.begin(); for ( int i=0; i<100000; i++ ) { Customer customer = new Customer(.....); em.persist(customer); if ( i % 20 == 0 ) { //20, same as the JDBC batch size //flush a batch of inserts and release memory: em.flush(); em.clear(); } } tx.commit(); session.close(); 

在这种情况下使用Hibernate的专有API并不能提供任何IMO优势。

参考

  • JPA 1.0规范
    • 第4.10节“批量更新和删除操作”
  • Hibernate Core参考指南
    • 第13章批处理

具体来说,对于hibernate, 核心手册的第13章解释了这些方法。

但是你说你想通过Hibernate获得EJB方法,所以实体管理器文档在这里也有一章。 我建议您同时阅读(核心和实体经理)。

在EJB中,它只是使用EJB-QL(有一些限制)。 如果你需要更多的灵活性,Hibernate提供了更多的机制。

使用中等记录编号,您可以使用以下方式:

 em.getTransaction().begin(); for (int i = 1; i <= 100000; i++) { Point point = new Point(i, i); em.persist(point); if ((i % 10000) == 0) { em.flush(); em.clear(); } } em.getTransaction().commit(); 

但是对于大记录编号,您应该在多个事务中执行此任务:

 em.getTransaction().begin(); for (int i = 1; i <= 1000000; i++) { Point point = new Point(i, i); em.persist(point); if ((i % 10000) == 0) { em.getTransaction().commit(); em.clear(); em.getTransaction().begin(); } } em.getTransaction().commit(); 

参考: JPA批量商店

是的,如果您希望拥有您定义的控件,则可以回滚到JPA实现。

JPA 1.0在EL-HQL上很丰富,但对Criteria API的支持很少,但这已在2.0中得到解决。

 Session session = (Session) entityManager.getDelegate(); session.setFlushMode(FlushMode.MANUAL); 

帕斯卡尔

在您的示例中插入100000条记录,它是在单个事务中完成的,因为commit()仅在结束时调用。它是否对数据库施加了很大的压力? 此外,如果有回滚,成本将太高..

以下方法会更好吗?

 EntityManager em = ...; for ( int i=0; i<100000; i++ ) { if(!em.getTransaction().isActive()) { em.getTransaction().begin(); } Customer customer = new Customer(.....); em.persist(customer); if ((i+1) % 20 == 0 ) { //20, same as the JDBC batch size //flush and commit of inserts and release memory: em.getTransaction().commit(); em.clear(); } } session.close();