A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© HM代景康 高级黑马   /  2013-10-17 22:41  /  1019 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

Hibernate的批量处理  Hibernate完全以面向对象的方式来操作数据库,当程序里以面向对象的方式操作持久化对象时,将被自动转换为对数据库的操作。例如调用Session的delete()方法来删除持久化对象,Hibernate将负责删除对应的数据记录;当执行持久化对象的set方法时,Hibernate将自动转换为对应的update方法,修改数据库的对应记录。
  问题是如果需要同时更新100?000条记录,是不是要逐一加载100?000条记录,然后依次调用set方法——这样不仅繁琐,数据访问的性能也十分糟糕。对这种批量处理的场景,Hibernate提供了批量处理的解决方案,下面分别从批量插入、批量更新和批量删除3个方面介绍如何面对这种批量处理的情形。
  4.2.1 批量插入
  如果需要将100?000条记录插入数据库,通常Hibernate可能会采用如下做法:
  Session session = sessionFactory.openSession();
  Transaction tx = session.beginTransaction();
  for ( int i=0; i<100000; i++ ) {
  User u = new User (.....);
  session.save(customer);
  }
  tx.commit();
  session.close();
  但随着这个程序的运行,总会在某个时候运行失败,并且抛出OutOfMemoryException(内存溢出异常)。这是因为Hibernate的Session持有一个必选的一级缓存,所有的User实例都将在Session级别的缓存区进行了缓存的缘故。
  为了解决这个问题,有个非常简单的思路:定时将Session缓存的数据刷新入数据库,而不是一直在Session级别缓存。可以考虑设计一个累加器,每保存一个User实例,累加器增加1。根据累加器的值决定是否需要将Session缓存中的数据刷入数据库。
  下面是增加100?000个User实例的代码片段:
  private void testUser()throws Exception
  {
  //打开Session
  Session session = HibernateUtil.currentSession();
  //开始事务
  Transaction tx = session.beginTransaction();
  //循环100 000次,插入100 000条记录
  for (int i = 0 ; i < 1000000 ; i++ )
  {
  //创建User实例
  User u1 = new User();
  u1.setName("xxxxx" + i);
  u1.setAge(i);
  u1.setNationality("china");
  //在Session级别缓存User实例
  session.save(u1);
  //每当累加器是20的倍数时,将Session中的数据刷入数据库,并清空Session缓存
  if (i % 20 == 0)
  {
  session.flush();
  session.clear();
  tx.commit();
  tx = session.beginTransaction();
  }
  }
  //提交事务
  tx.commit();
  //关闭事务
  HibernateUtil.closeSession();
  }
  上面代码中,当i%20 == 0时,手动将Session处的缓存数据写入数据库,并手动提交事务。如果不提交事务,数据将依然缓存在事务处——未进入数据库,也将引起内存溢出的异常。
  这是对Session级别缓存的处理,还应该通过如下配置来关闭SessionFactory的二级 缓存。
  hibernate.cache.use_second_level_cache false
  注意:除了要手动清空Session级别的缓存外,最好关闭SessionFactory级别的二级缓存。否则,即使手动清空Session级别的缓存,但因为在SessionFactory级别还有缓存,也可能引发异常。

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马