Hibernate批处理有什么用?

时间:2014-12-13 06:36:12

标签: java hibernate batch-processing

我是hibernate的新手我对hibernate批处理有疑问,我读了一些关于hibernate批处理的教程他们说

Session session = SessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) 
{
  Employee employee = new Employee(.....);
  session.save(employee);

}
tx.commit();
session.close();

Hibernate将缓存会话级缓存中的所有持久对象,最终你的应用程序会在第50,000行左右的某个地方出现OutOfMemoryException。如果您使用Hibernate批处理,

,则可以解决此问题
Session session = SessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) 
{
 Employee employee = new Employee(.....);
 session.save(employee);
 if( i % 50 == 0 ) 
 { // Same as the JDBC batch size
   //flush a batch of inserts and release memory:
   session.flush();
   session.clear();
 }
}
tx.commit();
session.close();

我怀疑的不是在外面初始化会话,为什么我们不能将它初始化为for循环,

Session session = null;
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) 
{
 session =SessionFactory.openSession()
 Employee employee = new Employee(.....);
 session.save(employee);
}
tx.commit();
session.close();

是否正确的方式是否有人建议我正确的方法?

3 个答案:

答案 0 :(得分:3)

没有。不要在for循环中初始化会话;每次开始新会话时,您都要开始一个新批处理(因此您的批处理大小为一个,即非批处理)。而且,你的方式会慢很多很多。这就是为什么第一个例子有

if( i % 50 == 0 ) { 
  //flush a batch of inserts and release memory:
  session.flush();
  session.clear();
}

这就是&#34;刷新一批插入并释放内存&#34;是为了。

答案 1 :(得分:2)

Batch Processing中的

Hibernate表示将大量任务划分为一些较小的任务。

当你解雇session.save(obj)时,hibernate实际上会将该对象缓存到其内存中(仍然没有将对象写入数据库),并在提交事务时将其保存到数据库,即当你调用{{1 }}

假设您要插入数百万条记录,因此触发transactrion.commit()会占用大量内存,最终会导致session.save(obj)

解决方案: 创建一个较小的简单批量并将其保存到数据库。

OutOfMemoryException

注意: 在上面的代码中,if( i % 50 == 0 ) { //flush a batch of inserts and release memory: session.flush(); session.clear(); } session.flush(),即实际将对象保存到数据库中,flush将清除这些对象占用的任何内存,用于批量为50的批次。

答案 2 :(得分:0)

正如我在this article中所解释的那样,批处理允许您优化写入数据。

但是,刷新和清除Hibernate会话的通常建议是不完整的。

您需要在批处理结束时提交事务,以避免长时间运行的事务,这可能会影响性能,如果最后一项失败,撤消所有更改将对数据库施加很大压力。

因此,您应该如何进行批处理:

int entityCount = 50;
int batchSize = 25;

EntityManager entityManager = entityManagerFactory().createEntityManager();

EntityTransaction entityTransaction = entityManager.getTransaction();

try {
    entityTransaction.begin();

    for (int i = 0; i < entityCount; i++) {
        if (i > 0 && i % batchSize == 0) {
            entityTransaction.commit();
            entityTransaction.begin();

            entityManager.clear();
        }

        Post post = new Post(
            String.format("Post %d", i + 1)
        );

        entityManager.persist(post);
    }

    entityTransaction.commit();
} catch (RuntimeException e) {
    if (entityTransaction.isActive()) {
        entityTransaction.rollback();
    }
    throw e;
} finally {
    entityManager.close();
}