`
tianlovv
  • 浏览: 14898 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

hibernate中批量处理的解决方案

阅读更多

实际开发中的一些问题:
批量的修改数据库字段(大数据量),

因为hibernate中提供了批量处理 的解决方案


Hibernate批量处理其实从性能上考虑,它是很不可取的,浪费了很大的内存。从它的机制上讲,Hibernate它是先把符合条件的数据查出来,放到内存当中,然后再进行操作。实际使用下来性能非常不理想,在笔者的实际使用中采用下面的第三种优化方案的数据是:100000条数据插入数据库,主流台式机的配置,需要约30分钟,呵呵,晕倒。
总结下来有三种来处理以解决性能问题:

 


1:绕过Hibernate API ,直接通过 JDBC API 来做,这个方法性能上是比较好的。也是最快的。
2:运用存储过程。
3:还是用Hibernate API 来进行常规的批量处理,可以也有变,变就变在,我们可以在查找出一定的量的时候,及时的将这些数据做完操作就
删掉,session.flush();session.evict(XX对象集); 这样也可以挽救一点性能损失。这个“一定的量”要就要根据实际情况做定量参考了。一般为30-60左右,但效果仍然不理想。
1:绕过Hibernate API ,直接通过 JDBC API 来做,这个方法性能上是比较好的,也是最快的。(实例为 更新操作)
Transaction tx=session.beginTransaction(); //注意用的是hibernate事务处理边界
Connection conn=session.connection();
PreparedStatement stmt=conn.preparedStatement("update CUSTOMER as C set C.sarlary=c.sarlary+1 where c.sarlary>1000");
stmt.excuteUpdate();
tx.commit(); //注意用的是hibernate事务处理边界
这小程序中,采用的是直接调用JDBC 的API 来访问数据库,效率很高。避免了Hibernate 先查询出来加载到内存,再进行操作引发的性能问题

2:运用存储过程。但这种方式考虑到易植和程序部署的方便性,不建议使用.(实例为 更新操作)如果底层数据库(如Oracle)支持存储过程,也可以通过存储过程来执行批量更新。存储过程直接在数据库中运行,速度更加快。在Oracle数
据库中可以定义一个名为batchUpdateCustomer()的存储过程,代码如下:

代码内容
create or replace procedure batchUpdateCustomer(p_age in number) as
begin
update CUSTOMERS set AGE=AGE+1 where AGE>p_age;
end; 

以上存储过程有一个参数p_age,代表客户的年龄,应用程序可按照以下方式调用存储过程:
代码内容
tx = session.beginTransaction();
Connection con=session.connection();
String procedure = "{call batchUpdateCustomer(?) }";
CallableStatement cstmt = con.prepareCall(procedure);
cstmt.setInt(1,0); //把年龄参数设为0
cstmt.executeUpdate();
tx.commit(); 

从上面程序看出,应用程序也必须绕过Hibernate API,直接通过JDBC API来调用存储过程。
3:还是用Hibernate API 来进行常规的批量处理,可以也有变,变就变在,我们可以在查找出一定的量的时候,及时的将这些数据做完操作就删掉,session.flush();session.evict(XX对象集); 这样也可以挽救一点性能损失。这个“一定的量”要就要根据实际情况做定量参考了。。
(实例为 保存操作)
业务逻辑为:我们要想数据库插入10 0000 条数据
tx=session.beginTransaction();
for(int i=0;i[size=x-small;]         {
                  session.flush();
                  session.clear();
         }
}

这样可以把系统维持在一个稳定的范围

批量插入:
//打开session
Session session = sessionFactory.openSession();
Transaction tx = session.begainTransaction();
//循环100000次,插入100000条记录
for(int i = 0;i<=100000;i++){
           //创建User实例
           User u1 = new User();
           u1.setName("XXXX"+i);
           u1.setAge(i);
           u1.setAddress("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();

 

 

hibernate中2级缓存还需配置:hibernate.cache.use_second_level_cache false



批量更新:
//打开session

Session session = sessionFactory.openSession();
//开始事物
Transaction tx = session.begainTransaction();
//查询出User表中的所有数据
ScrollableResult user = session.createQuery("from user")
           .setCacheMode(Cache.Mode.IGNORE).scroll(ScrollMode.FOREARD_ONLY);
int count = 0;
//遍历user表中所有的记录
while (user.next()){
           User u = (User)users.get(0);
           u.setName("新用户名"+count);
           //当count为20的倍数时,将更新的结果从session中刷新到数据库
           if(++count%20==0){
                       session.flush();
                       session.clear();
           }
}
//提交事物
tx.commit();
//关闭事物
hibernateUtil.closeSession();
但是这种风格的语句性能较低

可以使用hibernate提供的HQL批量的更新和删除 UPDATE|DELETE FROM? ClassName [WHERE WHERE_CONDITIONS]
假设批量更新User类实例的name属性,可以如下代码:
private void testUser()throws Exception{
            //打开session            
            Session session = sessionFactory.openSession();
            //开始事物
            Transaction tx = session.begainTransaction();
            //定义批量更新的HQL语句
            String hqlUpdate = "update User set name =:newName";
            //执行更新
            int updateEntities = session.createQuery(hqlUpdate)
                                 .setString("newName","新名字").executeUpdate();
            //提交事物
            tx.commit();
            //关闭事物
            hibernateUtil.closeSession();
}
批量的删除HQL:
private void testUser()throws Exception{
            //打开session
            Session session = sessionFactory.openSession();
            //开始事物
            Transaction tx = session.begainTransaction();
            //定义批量更新的HQL语句
            String hqlUpdate = "delete User";
            //执行批量删除
            int updateEntities = session.createQuery(hqlUpdate).executeUpdate();
            //提交事物
            tx.commit();
            //关闭事物
            hibernateUtil.closeSession();
}
Query.executeUpdate()方法返回 的是一个整型值,该值是受此操作影响的记录条数

分享到:
评论

相关推荐

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

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

    Hibernate中大量数据的更新

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

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

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

    Java中Hibernate的批量插入

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

    Hibernate

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

    ssh(structs,spring,hibernate)框架中的上传下载

     以上是Spring+Hibernate将文件二进制数据持久化到数据库的解决方案,而Struts通过将表单中file类型的组件映射为ActionForm中类型为org.apache.struts.upload. FormFile的属性来获取表单提交的文件数据。  工程...

    Spring.3.x企业应用开发实战(完整版).part2

    12.2 在Spring中使用Hibernate 12.2.1 配置SessionFactory 12.2.2 使用HibernateTemplate 12.2.3 处理LOB类型数据 12.2.4 添加Hibernate事件监听器 12.2.5 使用原生Hibernate API 12.2.6 使用注解配置 12.2.7 事务...

    Spring3.x企业应用开发实战(完整版) part1

    12.2 在Spring中使用Hibernate 12.2.1 配置SessionFactory 12.2.2 使用HibernateTemplate 12.2.3 处理LOB类型数据 12.2.4 添加Hibernate事件监听器 12.2.5 使用原生Hibernate API 12.2.6 使用注解配置 12.2.7 事务...

    DWR中文文档.pdf

    42 4.8.2 解决方案 42 &lt;br/&gt;第5章. DWR中的JavaScript简介 44 5.1 简单的回调函数 44 5.2 调用元数据对象 45 5.3 查找回调函数 45 5.4 创造一个与Java对象匹配的Javascript对象 46 &lt;br/...

    Spring中文帮助文档

    在表单中处理分段文件上传 13.9. 使用Spring的表单标签库 13.9.1. 配置 13.9.2. form标签 13.9.3. input标签 13.9.4. checkbox标签 13.9.5. checkboxes标签 13.9.6. radiobutton标签 13.9.7. radiobuttons...

    WODECMS开源内容管理系统 v1.1.zip

    我的CMS设计上尽量简单,不为了追求某种"高大上"的技术解决方案而无计划的采纳和叠加,只为简单和适用而设计。作为开发者入门门槛低,系统扩展性好;目前已经广泛应用于移动开发,电商平台,微信公众平台等领域。它...

    java开源包1

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包11

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包2

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包3

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包6

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包5

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包10

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包4

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

Global site tag (gtag.js) - Google Analytics