`
leogao_emcom
  • 浏览: 81618 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

使用Hibernate进行数据的批量更新

阅读更多
当我们使用SQL直接在数据库里面操作是,批量更新一大批数据是很快捷的,比如
update Companys set BidPrice='1000' where Name='MS'
不管有多少条Name='MS'的记录都会被更新,而且直接作用于数据至少比较快。
但是当我们使用Hibernate的时候,事情就有点变化了,当我们必须批处理如以上的数据时,假定有10000条,那么我们必须先Query(..).List出10000个Company对象,而这些对象会马上加载到Hibernate的第一级缓存中,也就是Session缓存,成为持久化对象(PO),
在更新他们的时候:
 
  Iterator Compamys=session.createQuery("from Company where Name='MS'").list().iterator();
  while(Companys.hasNext())
  {
      Company comany=(Company)Companys.next();
      company.setBidPrice(1000);
  }
  tx.commit();
  Session.close();
  

  加载大量的PO会消耗很多内存,更加可怕的是,在加载PO的时候,Hibernate会产生数据的快照以便用来生成最终的SQL语句,当commit的时候,就会根据快照和实际PO的属性值进行比较,一旦发现有变化的属性,就会生成一个SQL语句,换句话说上面这点代码不仅要占用10000个Company对象的内存,还要生成10000个SQL语句。
  所以有人想出限制批量的数量,把Hibernate缓存限制到一个数量,比如20,也就是说缓存中只能存在20个PO,然后在上面的代码中加计数,一旦遍历的数量达到20,就Flush,这里就不贴出代码了,我想说明的是这样的方式是治标不治本,还是会产生20个SQL语句,另外10000个PO对象,只是分批次(每批20个)载入缓存和分批次产生20个SQL,一共500批,客户机的负载是小了,但是数据库方面让然不容乐观,另外就是网络通信还是10000次,这是一个很笨的做法。
   另外如果有人开启了第二级缓存,那好,Hibernate会把在第一级缓存做的事情再做一次,结果重新发生了10000次更新操作,也就是总共20000次的操作。
    有人想用StatelessSession来执行批量更新,因为至少PO不会进入缓存,都是游离状态的对象了,也就不会占用缓存,由于没有被缓存引用,那么只要这个游离的PO被引用=0,就会被JVM垃圾收集掉,至少很大部分不用占用了,但是也许问题更大,因为在确认一个属性是否跟新过了而产生一个对应的SQL前必须先查询数据库,因为这些对象都是游离对象,没有快照支持,所以必须在更新之前查询一下数据库,也就是说每更新一次就得查询一次,这下好了,如果批量跟新10000个,也就必须查询10000次,数据库的压力上来了!也是不太好的办法。
     估计有人还会想出来,直接JDBC吧,那么我们就是失去了使用Hibernate的机会,也就享受不到它提供的各种优于直接使用JDBC的好处,另外在结构上就成了混合型,结构不整洁了。
      那怎么办?其实直接用HQL就可以:
     
       String hqlStatement="update Company m set m.BiDPrice=:NewPrice where m.Name=:ComName";
       int updatedEntities=session.createQuery(hqlStatement)
           .setString("NewPrice","1000")
           .setString("ComName","MS")
           .executeUpdate();
        tx.commit();
        session.close();
     

     它不需要缓存,另外只生成一条SQL update语句,客户机内存和服务器的负载都很低,就和直接使用SQL一样,但是还是有些性能损失的,至少Hibernate必须根据方言把上面的HQL转换成能够执行的SQL,需要一定的CPU时间。但是这样少的损失是可以忍受的,毕竟就是一次计算的过程,即使二级缓存被打开,也不会产生什么副作用了。
      但是也不并是说任何场合下使用HQL都很高效,比如取得一个Company对应的所有订单,如果用HQL就会马上为所有这些订单对象填充数据,如果用Company.getOrders()就会好的多,因为我们可以在hbm映射文件中将Company的lazy=true,这样就有了延迟加载的能力,也就是说,我们在调用Company,getOrders才开始加载数据,不用的时候不加载。
      其实,批量更新,如果用Hibernate调用存储过程,就更加快捷,网络交通只是一存储过程的名称和参数,比写一个HQL更加简短有效!
      
0
0
分享到:
评论
1 楼 liangguanhui 2010-11-03  
有一次去一个公司笔试的时候,有一道题目是关于HQL可以干啥,当时选了Query,后来才发现原来可以可以跟普通SQL一样DML。当然,一级缓存就失去了对这些对象的控制了。

相关推荐

    Hibernate下数据批量处理解决方案

    很多人都对Java在批量数据的处理方面是否是其合适的场所持有怀疑的念头,由此延伸,...下面以Hibernate为例来做为说明,假如我们真的不得不在Java中使用Hibernate来对数据进行批量处理的话。 向数据库插入100 000条数据

    Hibernate中大量数据的更新

    使用Hibernate将大量记录插入到数据库

    2022年Hibernate下数据批量处理Java教程.docx

    2022年Hibernate下数据批量处理Java教程.docx

    hibernate批量删除

    在我们的Java项目中,批量更新是指在一个事务中更新大批量数据,批量删除是指在一个事务中删除大批量数据。批量删除虽然在Hibernate里也可以实现,但...其实Hibernate提供的JDBC接口,可以方便的进行批量的更新和删除。

    jsp Hibernate批量更新和批量删除处理代码

    批量更新是指在一个事务中更新大批量数据,批量删除是指在一个事务中删除大批量数据。

    浅析Hibernate下数据批量处理方法.doc

    不建议用Hibernate,它的insert效率实在不搞,不过最新版本的Hibernate似乎已经在批量处理的时候做过优化了,设置一些参数如batch_size,不过性能我没有测试过

    Hibernate实现批量添加数据的方法

    主要介绍了Hibernate实现批量添加数据的方法,详细分析了基于Hibernate执行批量添加操作的具体步骤与相关实现代码,需要的朋友可以参考下

    Hibernate配置各种数据源详解

    Hibernate配置各种数据源 <hibernate-configuration> <!– 各属性的配置–> <!—为true表示将Hibernate发送给数据库的sql显示出来 –> ...– 设定对数据库进行批量删除 –> ”jdbc.batch_size”>30</property>

    Hibernate批量处理数据

    看完该文件你就可以最高效率的批量处理数据

    Hibernate批量处理海量数据的方法

    主要介绍了Hibernate批量处理海量数据的方法,较为详细的分析了Hibernate批量处理海量数据的原理与相关实现技巧,需要的朋友可以参考下

    Java中Hibernate的批量插入

    Hibernate完全以面向对象的方式来操作数据库,当程序里以面向对象的方式操作持久化对象时,将被自动转换为对数据库的操作。...为了面对这种批量处理的场景,Hibernate提供了批量处理的解决方案。下面分别

    Hibernate批量处理

    高效的进行批量数据的处理方案,留作参考。

    Hibernate管理Session和批量操作分析

    主要介绍了Hibernate管理Session和批量操作的技巧,包括Hibernate管理Session、批量处理数据等的常用技巧及注意事项,具有一定的参考借鉴价值,需要的朋友可以参考下

    Hibernate

    Hibernate下数据批量处理解决方案

    让hibernate输出sql语句参数配置.doc

    hibernate.order_updates 参数用于强制 Hibernate 按照被更新数据的主键,为 SQL 更新排序。其取值为 true 或 false。 11. hibernate.generate_statistics hibernate.generate_statistics 参数用于如果开启,...

    hibernate.cfg.xml中配置信息详解

    如果设置为非零值,Hibernate 将使用 JDBC2 的批量更新。 hibernate.jdbc.batch_versioned_data Hibernate.jdbc.batch_versioned_data 属性用于控制 Hibernate 是否使用批量 DML。如果设置为 true,Hibernate 将...

    Hibernate+中文文档

    3.2. Hibernate数据源属性 3.3. Hibernate配置属性 3.4. Hibernate JDBC和连接(connection)属性 3.5. Hibernate缓存属性 3.6. Hibernate事务属性 3.7. 其他属性 3.8. Hibernate SQL方言 (hibernate.dialect) ...

    hibernate基础教程

    在Hibernate中使用两极缓存结构,第一级缓存是Session级别的缓存,Session级别的缓存是由Hibernate管理的,一般情况下无需进行干预.第二级缓存是 SessionFactory级别的缓存,SessionFactory级的缓存可以进行配置和...

    彻底解决hibernate常见难点.zip

    Hibernate处理1-N关系时保存技巧、Hibernate缓存机制、Hibernate批量处理数据、Hibernate三种继承映射策略、hibernate映射体系、Hibernate主键生成策略、持久层DAO设计建议、基于xml文件的bean、使用HibernateAPI在...

    HibernateAPI中文版.chm

    3.2. Hibernate数据源属性 3.3. Hibernate配置属性 3.4. Hibernate JDBC和连接(connection)属性 3.5. Hibernate缓存属性 3.6. Hibernate事务属性 3.7. 其他属性 3.8. Hibernate SQL方言 (hibernate.dialect) ...

Global site tag (gtag.js) - Google Analytics