JPA/EJB3的批量插入

25

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

5个回答

23

既然 JPA 也不提供特定的批量插入支持,因此 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没有任何优势。

参考资料

  • JPA 1.0规范
    • 第4.10节“批量更新和删除操作”
  • Hibernate核心参考指南

为了保持清醒,请检查您的 if 语句是否为 i > 0 && i % 20 == 0,否则它将在添加第一个元素后立即刷新(并清除)。 - Buhake Sindi

6

如果记录数量较中等,您可以使用以下方法:

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批量存储


5

对于Hibernate,整个核心手册第13章都解释了方法。

但是你说你想通过Hibernate使用EJB方法,因此实体管理器文档也有相关章节在这里。我建议你阅读核心和实体管理器两个部分。

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


1

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

JPA 1.0在EL-HQL方面非常丰富,但在Criteria API支持方面较轻,不过这在2.0中已得到解决。

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

1

Pascal

在您插入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();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接