首页 > 在Hibernate中处理批量更新和批量删除

在Hibernate中处理批量更新和批量删除

批量更新是指在一个事务中更新大批量数据,批量删除是指在一个事务中删除大批量数据。以下程序直接通过Hibernate API批量更新CUSTOMERS表中年龄大于零的所有记录的AGE字段: 如果CUSTOMERS表中有1万条年龄大于零的记录,那么Session的find()方法会一下子加载1万个Customer对象到内存。当执行tx.commit()方法时,会清理缓存,Hibernate执行1万条更新CUSTOMERS表的update语句:

view plaincopy to clipboardprint?

update CUSTOMERS set AGE=? …. where ID=i;   update CUSTOMERS set AGE=? …. where ID=j;   ……   update CUSTOMERS set AGE=? …. where ID=k;   update CUSTOMERS set AGE=? …. where ID=i;update CUSTOMERS set AGE=? …. where ID=j;……update CUSTOMERS set AGE=? …. where ID=k;

以上批量更新方式有两个缺点: (1)占用大量内存,必须把1万个Customer对象先加载到内存,然后一一更新它们。

(2)执行的update语句的数目太多,每个update语句只能更新一个Customer对象,必须通过1万条update语句才能更新一万个Customer对象,频繁的访问数据库,会大大降低应用的性能。为了迅速释放1万个Customer对象占用的内存,可以在更新每个Customer对象后,就调用Session的evict()方法立即释放它的内存:

view plaincopy to clipboardprint?

tx = session.beginTransaction();   Iterator customers=session.find("from Customer c where c.age>0").iterator();   while(customers.hasNext()){   Customer customer=(Customer)customers.next();   customer.setAge(customer.getAge()+1);   session.flush();   session.evict(customer);   }    tx.commit();   session.close();   tx = session.beginTransaction();Iterator customers=session.find("from Customer c where c.age>0").iterator();while(customers.hasNext()){Customer customer=(Customer)customers.next();customer.setAge(customer.getAge()+1);session.flush();session.evict(customer);} tx.commit();session.close();

在以上程序中,修改了一个Customer对象的age属性后,就立即调用Session的flush()方法和evict()方法,flush()方法使Hibernate立刻根据这个Customer对象的状态变化同步更新数据库,从而立即执行相关的update语句;evict()方法用于把这个Customer对象从缓存中清除出去,从而及时释放它占用的内存。 但evict()方法只能稍微提高批量操作的性能,因为不管有没有使用evict()方法,Hibernate都必须执行1万条update语句,才能更新1万个Customer对象,这是影响批量操作性能的重要因素。假如Hibernate能直接执行如下SQL语句: update CUSTOMERS set AGE=AGE+1 where AGE>0; 那么,以上一条update语句就能更新CUSTOMERS表中的1万条记录。但是Hibernate并没有直接提供执行这种update语句的接口。应用程序必须绕过Hibernate API,直接通过JDBC API来执行该SQL语句:

view plaincopy to clipboardprint?

tx = session.beginTransaction();   Connection con=session.connection();   PreparedStatement stmt=con.prepareStatement("update CUSTOMERS set AGE=AGE+1 "  +"where AGE>0 ");   stmt.executeUpdate();   tx.commit();   tx = session.beginTransaction();Connection con=session.connection();PreparedStatement stmt=con.prepareStatement("update CUSTOMERS set AGE=AGE+1 "+"where AGE>0 ");stmt.executeUpdate();tx.commit();



以上程序演示了绕过Hibernate API,直接通过JDBC API访问数据库的过程。应用程序通过Session的connection()方法获得该Session使用的数据库连接,然后通过它创建PreparedStatement对象并执行SQL语句。值得注意的是,应用程序仍然通过Hibernate的Transaction接口来声明事务边界。

转载于:https://www.cnblogs.com/soundcode/archive/2010/12/20/1911941.html

更多相关:

  • Term::ProgressBar 模块是一个可以用于生成进度条的 Perl 模块。安装:cpan -i Term::ProgressBar最小脚本,展示如何最快学会使用该模块:#!/usr/bin/env perluse strict; use warnings; use Term::ProgressBar 2.00;my $max...

  • 当我们勾选了同步(Update Project)弹窗的 “Do not show this dialog in the future(以后不显示此对话框)” 的复选框☑   以后再次使用同步功能(Update Project)时 不会再出现这个弹窗(如下图),这就导致了我们无法修改Update Type和Clean workin...

  • mapper.xml文件,后台传入一个对象集合,另外如果是mysql数据库,一点在配置文件上加上&allowMultiQueries=true,这样才可以执行多条sql,以下为mysql:

  • Time类包含了一个重要的类变量deltaTime,它表示距上一次调用Update或FixedUpdate所用的时间。 因此通过它可以让游戏对象按照一个常速进行旋转,而不是依赖于它的帧频: function Update() {    tranform.Rotate(0, 5 * Time.deltaTime, 0); }  同样地移...