梦相随1006

版权归 梦相随1006 所有,未经 https://www.cnblogs.com/xin1006 作者许可,严禁转载

导航

Hibernate批处理操作优化 (批量插入、更新与删除)

 

Hibernate的一级缓存影响。

        我们每次保存的东西都会保存在Session缓存中,这就是Hibernate的一级缓存,如果我们一直循环执行save等操作,缓存里东西会越来越多,速度也就越来越慢,服务器一直在循环处理,自然也会增加负载。

       这本来就是Hibernate不擅长的地方,而且一级缓存不可以不用,如果我们要保存的数据量十分巨大,那么在程序中执行添加、更新方法时,Session对象自身开辟的一级缓存会不断消耗,直至OutOfMemoryError (内存溢出异常)。

解决方案

 

批量插入优化

 

    1、仍旧用Hibernate API来进行批处理,但在一定的量的时候,及时的清除缓存。

 

     1)优化Hibernate,在配置文件中设置hibernate.jdbc.batch_size参数,来指定每次提交SQL的数量。 配置hibernate.jdbc.batch_size参数的原因就是尽量少读数据库,hibernate.jdbc.batch_size参数值越大,读数据库的次数越少,速度越快。

 

<!--设置hibernate.jdbc.batch_size参数-->
<hibernate-configuration>
    <session-factory>
        .........
        <property name="hibernate.jdbc.batch_size">50</property>
        .........
    <session-factory>
<hibernate-configuration>

 

   2)程序及时清除缓存,即每插入一定量的数据后及时把它们从内部缓存中清除掉,释放占用的内存

 

     如下代码:

 

// 每处理50条清空缓存
session.save(myObject);
if (i%50 == 0) {
    session.flush();
    session.clear();
}

// 在我的项目中写法如下:
if (i%50 == 0) {
    this.getHibernateTemplate().flush();
    this.getHibernateTemplate().clear();
}

 

  2、通过JDBC API来做批量插入,绕过Hibernate API。这个方法性能上是最好的,也是最快的。

     由于session.connection()方法已经过时,我们可以通过下面方法获得Connection连接,但是仍然可以使用的

  private Connection getJdbcConnection(){
       
          //1,获取SessionFactory
          SessionFactory factory=super.getHibernateTemplate().getSessionFactory();
          //2,获取数据源
          DataSource ds=SessionFactoryUtils.getDataSource(factory);
          try {

    //3,通过数据源获取Jdbc连接
              return ds.getConnection();
          } catch (SQLException e) {
              logger.error("Hibernate-->Jdbc时没有获取到连接...", e);
          }
          return null;
      }

 

 

示例代码:

 

String insertSql = "insert into user(name,address) values(?,?)";
Session session = getHibernateTemplate().getSessionFactory().openSession();
Connection conn = session.connection();
PrepareStatement stmt = conn.prepareStatement(insertSql);

// 方式1:自动提交
conn.setAutoCommit(true);
for(int i = 0; i++; i<10000) {
    stmt.setString(1, "testName");
    stmt.setString(2, "testAddress");
    stmt.execute();
}

// 方式2:批量提交
conn.setAutoCommit(false);
for(int i = 0; i++; i<10000) {
    stmt.setString(1, "testName");
    stmt.setString(2, "testAddress");
    stmt.addBatch();
    if (i % 100 == 0) {
        stmt.executeBatch();
        conn.commit();
    }
}
stmt.executeBatch();
conn.commit();

// 关闭session
session.close();


 

 

批量更新与删除优化

 

Hibernate2中,对于批量更新/删除操作,都是先将符合要求的数据查出来,然后再做更新/删除操作。这样一来会占用大量内存,而且海量数据处理的时候性能很低。

 

而Hibernate3对批量更新/删除提供了支持,能够直接执行批量更新或批量删除语句,无需把被更新或删除的对象先加载到内存中,类似于JDBC的批量更新/删除操作。

 

不过对于循环处理数据更新和删除场景,建议还是使用JDBC,方法同上:批量插入的方法2。

 

 

 

转自 : http://youngflying.com/2012/09/14/hibernate-batch-processing/

posted on 2013-05-09 13:34  梦相随1006  阅读(5493)  评论(0编辑  收藏  举报