Java 使用 JPA/EJB3 批量插入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/448181/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 14:45:38  来源:igfitidea点击:

Batch inserts with JPA/EJB3

javahibernateormjpabatch-insert

提问by Raja

Does JPA/EJB3 framework provide standard way to do batch insert operation...? We use hibernate for persistence framework, So I can fall back to Hibernate Session and use combination session.save()/session.flush() achieve batch insert. But would like to know if EJB3 have a support for this...

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

回答by Loki

For hibernate specifically, the whole chapter 13 of the core manualexplain the methods.

具体针对hibernate,核心手册的整个第13章解释了方法。

But you are saying that you want the EJB method through Hibernate, so the entity manager documentation also has a chapter on that here. I suggest that you read both (the core and the entity manager).

但是您是说您希望通过 Hibernate 使用 EJB 方法,因此实体管理器文档在这里也有一章。我建议您同时阅读(核心和实体管理器)。

In EJB, it is simply about using EJB-QL (with some limitations). Hibernate provides more mechanics though if you need more flexibility.

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

回答by JARC

Yes you can rollback to your JPA implementation if you wish in order to have the control you defined.

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

JPA 1.0 is rich on EL-HQL but light on Criteria API support, however this has been addressed in 2.0.

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

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

回答by Pascal Thivent

Neither JPA nor Hibernate do provide particular support for batch inserts and the idiom for batch inserts with JPA would be the same as with Hibernate:

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

Using Hibernate's proprietary API in this case doesn't provide any advantage IMO.

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

References

参考

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

回答by shudong

Pascal

帕斯卡

In your example to insert 100000 records, it is done within single transaction, as the commit() is only called at the end.. Does it put a lot pressure towards the database? Furthermore, in case there is rollback, the cost will be too much..

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

Will the following approach be better?

下面的方法会更好吗?

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

回答by Tho

With medium records number you can use this way:

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

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

But with large records number you should perform this task in multiple transactions:

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

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

Ref: JPA Batch Store

参考:JPA 批处理存储