使用 JPA/EJB3 批量插入

发布于 2024-07-12 13:13:41 字数 153 浏览 7 评论 0 原文

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

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...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

梦里兽 2024-07-19 13:13:47

特别是对于 hibernate,核心手册的第 13 章解释方法。

但是您说您希望通过 Hibernate 使用 EJB 方法,因此实体管理器文档也有一章关于该内容 此处。 我建议您阅读两者(核心和实体管理器)。

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

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

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).

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

眼眸里的快感 2024-07-19 13:13:47

是的,如果您希望获得您定义的控制,您可以回滚到您的 JPA 实现。

JPA 1.0 丰富了 EL-HQL,但缺乏 Criteria API 支持,不过这个问题已在 2.0 中得到解决。

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

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

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

Session session = (Session) entityManager.getDelegate();
session.setFlushMode(FlushMode.MANUAL);
恬淡成诗 2024-07-19 13:13:47

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

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..

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();
紙鸢 2024-07-19 13:13:46

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 不会提供任何优势。

参考

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:

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.

References

jJeQQOZ5 2024-07-19 13:13:46

对于中等记录数,您可以使用这种方式:

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文