我是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();
是否正确的方式是否有人建议我正确的方法?
答案 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();
}