1

我使用Hibernate 5.2.8.Final版本,我们有一个要求,我们从数据库读取数百万的数据,并通过一些业务逻辑更新数据,因为我的数据库是巨大的我想承诺达到我BATCHSIZE后的数据,所以我写了下面的代码花费很长时间冲洗中间使用休眠

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

public class Object implements Serializable 
    { 
     private static final long serialVersionUID = 1L; 

     @Id 
     @GeneratedValue(strategy = GenerationType.IDENTITY) 
     @Column(name = "ID", nullable = false, unique = true, updatable = false) 
     private int id; 
     private String filePath; 

    private String fileName; 
    private String mimeType; 
    private double fileSize; 
    // removed getters and setters 

    } 

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

+0

batchSizeDeclare的值是什么? – Thierry

+0

100是我的batchSizeDeclare值 – rajadilipkolli

回答

0

当我的代码到达session.flush后,它在等待30分钟后甚至没有做任何事情,即使是 。

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

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

简短的回答是没有

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

  1. 你可以做加工在数据库中,这样你不支付提取数据并发送它在网络上,只处理它在Java中的价格。
  2. 如果无法在DB <中处理它,则需要使用批处理器,该处理器一次只能获取小块数据。这样,您甚至可以并行处理批处理,这会减少整体处理时间。

解决这个问题的唯一方法就是改变你的方法。

+0

还有一个问题,我已将batchSizeDeclare变量设置为100,这是hibernate.cfg.xml文件值中的批量更新大小。对于100条记录将花30分钟以上,我也看到声明id值作为序列是最好的。更改值有助于提高性能 – rajadilipkolli

+0

记录SQL查询并确保仅执行100个条目。检查数据库日志以查看发生了什么也很重要。 –

+0

在SQL查询中,它只显示100个数据库,在db日志中插入另一批数据,其中还包含1000万条插入数据块的记录数据 – rajadilipkolli