花很长时间使用Hibernate进行中间刷新

时间:2017-02-23 13:10:35

标签: java hibernate orm batch-processing hibernate-batch-updates

我正在使用Hibernate 5.2.8.Final版本,我们有一个要求,我们从数据库中读取数百万个数据并通过某些业务逻辑更新数据,因为我的数据库是巨大的我想在达到批量化后提交数据所以我写了下面的代码

synchronized

以下是我的Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.getTransaction().begin(); Query<Object> query = session.createQuery(SQL, Object.class); ScrollableResults scrollableResults = query.setCacheMode(CacheMode.IGNORE) .scroll(ScrollMode.FORWARD_ONLY); int count = 0; while (scrollableResults.next()) { Object object = (Object) scrollableResults.get(0); process(object) session.update(object); if (++count % batchSizeDeclare== 0) { session.flush(); session.clear(); LOGGER.info("Updated batch records"); } } session.getTransaction().commit(); LOGGER.info("commited in Hibernate "); } 文件

hibernate.cfg.xml

以下是我的<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- Database connection settings --> <property name="connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property> <property name="connection.url">jdbc:sqlserver://com;database=DEV</property> <property name="connection.username">user</property> <property name="connection.password">pass</property> <property name="hibernate.default_schema">schema</property> <!-- JDBC connection pool (use the built-in) --> <property name="connection.pool_size">5</property> <!-- SQL dialect --> <property name="dialect">org.hibernate.dialect.SQLServer2012Dialect</property> <!-- Disable the second-level cache --> <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property> <!-- Echo all executed SQL to stdout --> <!-- <property name="show_sql">true</property> --> <!-- <property name="format_sql">true</property> --> <!-- Drop and re-create the database schema on startup --> <property name="hbm2ddl.auto">update</property> <!-- org.hibernate.HibernateException: No CurrentSessionContext configured! --> <property name="hibernate.current_session_context_class">thread</property> <property name="hibernate.jdbc.batch_size">100</property> <property name="hibernate.c3p0.min_size">5</property> <property name="hibernate.c3p0.max_size">20</property> <property name="hibernate.c3p0.timeout">300</property> <property name="hibernate.c3p0.max_statements">50</property> <property name="hibernate.c3p0.idle_test_period">3000</property> <mapping class="com.beans.Object" /> </session-factory> </hibernate-configuration>

Object.java

一旦我的代码到达session.flush(),即使在等待30分钟后也没有做任何事情。这是批量提交的正确方法吗?如何批量更新?

1 个答案:

答案 0 :(得分:0)

  

一旦我的代码到达session.flush,它甚至没有做任何事情   等了30分钟后。

恰恰相反!数据库做得太多了。只是你没有看到任何进展,因为数据库正在努力应对你提交的大量工作。

  

这是批量提交的正确方法吗?

简短的回答是

正如我在文章14 High-Performance Java Persistence Tips中所解释的那样,您不必从数据库中获取数百万行。你有更好的选择:

  1. 您可以在数据库中进行处理,这样您就不会为提取数据并通过网络发送数据付出代价,只能用Java处理它。
  2. 如果您无法在DB&lt;那么你需要使用批处理器,它一次只能获取一小块数据。这样,您甚至可以并行化批处理,这样可以缩短整体处理时间。
  3. 解决问题的唯一方法就是改变方法。