总结:hibernate在进行批量处理不给力的主要原因就是Session中存在缓存,而hibernate的机制就是通过session中的一级缓存去同步数据库,所以当进行批量处理时,缓存中保存的数据量很大时会消耗很大内存资源,造成各种崩溃。

  其实平时工作中用到大量的批处理数据还是挺少的,很少遇到有上万条数据的批处理的,但是要是遇到了用hibernate去处理还是很纠结的,然后就去Hibernate官网看了看有没有啥处理方法学习下。

  刚工作的时候用hibernate还不是很熟练,遇到批处理的时候就直接切到JDBC做处理,比较混搭的风格。但是感觉看上去代码风格就不是很好的感觉。

  批量插入:

  如果有10w条数据需要插入到数据库中用hibernate做起来可能会比较困难。

  比较too young too naive的做法就是循环:

1 Session session = sessionFactory.openSession();
2 Transaction tx = session.beginTransaction();
3 for ( int i=0; i<100000; i++ ) {
4 Customer customer = new Customer(.....);
5 session.save(customer);
6 }
7 tx.commit();
8 session.close();

  这样做法大概会在5w条数据时候跳出OutOfMemoryExcepiton,因为hibernate的一级缓存原因,会把数据都先缓存到session中,等事务commit或者flush的时候才会把数据同步到数据库中,数据量太大时候session就hold不住了你懂的。

  可以有个小聪明的做法,用下面方法之前,记得开启JDBC的批处理,在hibernate配置文件中设置hibernate.jdbc.batch_size属性值在10到50之间

 1 Session session = sessionFactory.openSession();
2 Transaction tx = session.beginTransaction();
3
4 for ( int i=0; i<100000; i++ ) {
5 Customer customer = new Customer(.....);
6 session.save(customer);
7 if ( i % 20 == 0 ) { //20, 和配置文件中hibernate.jdbc.batch_size属性值一致
8
9 session.flush(); //强制刷新session中的缓存到数据库中
10 session.clear(); //清除session中的缓存,ps:evict()干掉session中一个实例的缓存
11 }
12 }
13
14 tx.commit();
15 session.close();

  批量更新:

  批量更新的时候也可以利用fulsh()和clear()方法来定期的清楚session中的缓存,方法和上面的批量插入一样。除此之外,还可以用scroll()方法来处理当你想从数据库查询大量数据并想更新这些数据的时候,貌似有点游标的感觉啊:

  

 1 Session session = sessionFactory.openSession();
2 Transaction tx = session.beginTransaction();
3
4 ScrollableResults customers = session.getNamedQuery("GetCustomers")
5 .setCacheMode(CacheMode.IGNORE) // 设置cache模式为:这个session不会和cache有任何联系,不使用cache
6 .scroll(ScrollMode.FORWARD_ONLY);
7 int count=0;
8 while ( customers.next() ) {
9 Customer customer = (Customer) customers.get(0);
10 customer.updateStuff(...);
11 if ( ++count % 20 == 0 ) {
12 //同步数据并且释放内存:
13 session.flush();
14 session.clear();
15 }
16 }
17
18 tx.commit();
19 session.close();
org.hibernate.CacheMode的常量字段有:
  GET    session会从缓存中读取数据,但是不会把数据增加到缓存中,除非把缓存中的数据更新为无效数据时
  IGNORE  session不和任何缓存有交互操作,除非把缓存中的数据更新为无效数据时
  PUT    session不会从缓存中读取数据,但是会把从数据库中读取的数据增加到缓存中
  REFRESH  session不从缓存中读取数据,但是会把从数据库读取的数据增加到缓存中,和PUT不同的是会忽略配置文件中的hibernate.cache.use_minimal_puts属性,就是为了强制刷新缓存

 org.hibernate.ScrollMode的常量字段有:

  FORWARD_ONLY: 请求一个类似游标的结果集,并且只转发这个结果集

  SCROLL_INSENSITIVE:请求一个游标的结果集,并且对基础数据的变化不敏感

  SCROLL_SENSITIVE:请求一个游标的结果集,并且对基础数据变化敏感

  没有怎么用过这个属性,不怎么清楚是什么意思。以后有空会再研究下补充上来

通过StatelessSession来进行批处理
 1 StatelessSession session = sessionFactory.openStatelessSession();
2 Transaction tx = session.beginTransaction();
3
4 ScrollableResults customers = session.getNamedQuery("GetCustomers")
5 .scroll(ScrollMode.FORWARD_ONLY);
6 while ( customers.next() ) {
7 Customer customer = (Customer) customers.get(0);
8 customer.updateStuff(...); //做一些更新操作
9 session.update(customer);
10 }
11
12 tx.commit();
13 session.close();
Notes:通过StatelessSession查询返回的Customer的实例立刻会成为游离状态,不会关联到任何的持久化层的上下文中也不会和缓存有任何关联。因为StatelessSession本身也不包括一级缓存,所以就不用考虑有缓存溢出的问题。

  Notes:StatelessSession没有一级缓存,也不会和二级缓存和其他缓存有任何交互,不会隐式产生transaction更没有脏数据检查。

  StatelessSession是一个比较低级别的十分接近底层JDBC的抽象接口。它定义的insert(),update()和delete()的方法都是直接作用到数据库的数据中。和直接使用JDBC的SQL操作数据库效果一样,但是和Session接口中的save(),saveOrUpdate()还有delete()定义的操作有很大的不同。

最后的方法是可以通过HQL进行数据库的批量操作。这个会在后面的文章中继续提到的。

  下面是官方的原文,请原谅我的盗版:

http://docs.jboss.org/hibernate/orm/4.2/devguide/en-US/html/ch04.html

Hibernate 批处理(batch inserts, updates and deletes)的更多相关文章

  1. org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

    org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actua ...

  2. 20.org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

    org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actua ...

  3. 批处理(Batch)---批处理脚本。

    批处理(Batch),也称为批处理脚本.顾名思义,批处理就是对某对象进行批量的处理,通常被认为是一种简化的脚本语言,它应用于DOS和Windows系统中.批处理文件的扩展名为bat .目前比较常见的批 ...

  4. 关于Hibernate级联更新插入信息时提示主键不为空的问题“org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1 ”

    org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual ...

  5. JDBC06 其他操作及批处理Batch

    灵活指定SQL语句中的变量 -PreparedStatement 对存储过程进行调用 -CallableStatement 运用事务处理 -Transaction 批处理 -Batch -对于大量的批 ...

  6. Hibernate 批处理

    批处理 考虑一种情况,你需要使用 Hibernate 将大量的数据上传到你的数据库中.以下是使用 Hibernate 来达到这个的代码片段: Session session = SessionFact ...

  7. NHibernate官方文档中文版——批量插入(Batch inserts)

    A naive approach t7o inserting 100 000 rows in the database using NHibernate might look like this: 一 ...

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

    问题描述 我开发的网站加了个新功能:需要在线上处理表数据的批量合并和更新,昨天下午发布上线,执行该功能后,服务器的load突然增高,变化曲线异常,SA教育了我一番,让我尽快处理,将CPU负载降低. 工 ...

  9. 批处理[Batch]

    批处理 1. 定义:就是一堆DOS命令按一定顺序排列而形成的集合. 英文译为BATCH,批处理文件后缀BAT就取的前三个字母. 示例1:a.bat @echo off Netstat –a –n &g ...

随机推荐

  1. CF982C Cut 'em all!

    思路: 在深搜过程中,贪心地把树划分成若干个连通分支就可以了.划分的条件是某个子树有偶数个节点.注意到在一次划分之后并不需要重新计数,因为一个数加上一个偶数并不影响这个数的奇偶性. 实现: #incl ...

  2. poj3262 Protecting the Flowers

    思路: 简单贪心,每次选择性价比最高的. 实现: #include <iostream> #include <cstdio> #include <algorithm> ...

  3. ZIP解压缩文件的工具类【支持多级目录|全】

    ZIP解压缩文件的工具类[支持多级目录|全] 作者:Vashon 网上有很多的加压缩示例代码,但是都只是支持一级目录的操作,如果存在多级目录的话就不行了.本解压缩工具类经过多次检查及重构,最终分享给大 ...

  4. java将一个List赋值给另一个List的4种方法

    编辑 删除 声明:ArrayList a, 仅仅只是声明了一个list变量,其未来作用相当于C++中的引用变量,亦或者相当于一个对象块的索引,但并未为其分配具体的完整的对象所需要的内存空间,其所分配的 ...

  5. 更新github上的代码

    昨晚熬夜写完了"git上传本地项目代码到github"的任务,早上来公司先把早上的工作完成后,抽点时间继续来继续更新文章 更新github上的代码 一.克隆代码 1.把大神的代码c ...

  6. UVA 11419 SAM I AM (最小点覆盖,匈牙利算法)

    题意:给一个r*c的矩阵,某些格子中可能有一些怪物,可以在一行或一列防止一枚大炮,大炮会扫光整行/列的怪,问最少需要多少炮?输出炮的位置. 思路: 先每行和列都放一个炮,把炮当成点,把怪当成边,一边连 ...

  7. 循环实现数组filter方法

    // 循环实现数组 filter 方法 const selfFilter = function (fn, context){ // 如果调用的地方使用箭头函数,这里的this岂不是不对了,那该怎么解决 ...

  8. 【转】密码学 :CSP的概念

    转:[密码学]CSP的概念 CSP加密服务提供者(Cryptographic Service Provider)具有一下几个特点: CSP是真正执行密码运算的独立模块 物理上一个CSP由两部分组成:一 ...

  9. CentOS7.6 静态IP配置

    1:选中安装好的虚拟机,点击“编辑”,然后选择“虚拟网络编辑器(N…)”,如下图所示: 2:选择桥接模式,在桥接到指定的本地网卡即可."确定"保存 3:选中虚拟机,右击虚拟机,选择 ...

  10. ZOJ3228 Searching the String (AC自动机)

    Searching the String Time Limit: 7 Seconds                                      Memory Limit: 129872 ...