Hibernate批处理有什么用?

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

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

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

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

这是“冲洗一批插入和释放内存”的原因。

Hibernate Batch Processing意味着将大量任务划分为一些较小的任务。

当您触发session.save(obj) ,hibernate实际上会将该对象缓存到其内存中(仍然没有将对象写入数据库),并且在您提交事务时将其保存到数据库,即当您调用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即实际将对象保存到数据库中, session.clear()将清除这些对象占用的任何大小为50的批处理内存。

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

但是,刷新和清除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(); }