`

hibernate批量更新效果不好

    博客分类:
  • java
 
阅读更多

    批量更新是指在一个事务中更新大批量数据,批量删除是指在一个事务中删除大批量数据。以下程序直接通过Hibernate API批量更新CUSTOMERS表中年龄大于零的所有记录的AGE字段:
  

 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);
 } 
 tx.commit();
 session.close();



如果CUSTOMERS表中有1万条年龄大于零的记录,那么Session的find()方法会一下子加载1万个Customer对象到内存。当执行tx.commit()方法时,会清理缓存,Hibernate执行1万条更新CUSTOMERS表的update语句:
  

 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()方法立即释放它的内存:

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语句:

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接口来声明事务边界。

如果底层数据库(如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来调用存储过程。

Session的各种重载形式的update()方法都一次只能更新一个对象,而delete()方法的有些重载形式允许以HQL语句作为参数,例如:

session.delete("from Customer c where c.age>0");



如果CUSTOMERS表中有1万条年龄大于零的记录,那么以上代码能删除一万条记录。但是Session的delete()方法并没有执行以下delete语句

delete from CUSTOMERS where AGE>0;


Session的delete()方法先通过以下select语句把1万个Customer对象加载到内存中:

select * from CUSTOMERS where AGE>0;


接下来执行一万条delete语句,逐个删除Customer对象:

delete from CUSTOMERS where ID=i;
delete from CUSTOMERS where ID=j;
delete from CUSTOMERS where ID=k;




由此可见,直接通过Hibernate API进行批量更新和批量删除都不值得推荐。而直接通过JDBC API执行相关的SQL语句或调用相关的存储过程,是批量更新和批量删除的最佳方式,这两种方式都有以下优点:

(1) 无需把数据库中的大批量数据先加载到内存中,然后逐个更新或修改它们,因此不会消耗大量内存。

(2) 能在一条SQL语句中更新或删除大批量的数据。

分享到:
评论

相关推荐

    hibernate批量删除

    ### Hibernate批量删除详解 #### 背景与概念 在Java开发中,处理大量数据时,经常需要执行批量操作,如批量更新或批量删除。这些操作对于提高应用程序性能至关重要,尤其是在涉及成千上万条记录的情况下。...

    hibernate批量删除.txt

    在进行数据库操作时,经常会遇到需要批量处理数据的情况,例如批量更新或批量删除等。利用Hibernate框架可以方便地实现这些功能,提高开发效率并减少资源消耗。本文将详细介绍如何通过Hibernate进行批量删除,并探讨...

    Hibernate管理Session和批量操作分析

    2. **通过HQL(Hibernate Query Language)**:利用HQL语句实现批量操作,比如更新或删除,可以避免加载整个对象到内存。 3. **通过StatelessSession**:StatelessSession不维护任何持久化状态,没有一级缓存,适合...

    struts2+hibernate(文件批量上传至数据库+Ajax分页显示)

    前端通过Ajax异步请求这个结果,然后动态地更新DOM元素,实现分页效果。 为了实现这个功能,开发者需要熟悉以下技术: 1. Struts2框架的配置和Action编写。 2. Hibernate的实体类创建、持久化操作以及SQL映射。 3. ...

    hibernate中文参考文档

    - **Session**: Hibernate中的会话是执行数据库操作的基本单元,它提供了一种与数据库进行交互的方式,例如查询、更新等操作。 - **SessionFactory**: 用于创建Session的工厂类,是线程安全的,通常在整个应用中只...

    HIBERNATE检索策略

    批量加载策略能够显著减少数据库交互次数,特别是在处理大量数据时,对于提升整体性能有显著效果。 综上所述,HIBERNATE的检索策略是多样的,开发者可以根据具体的应用场景选择最合适的抓取和加载策略,以达到既...

    hibernate_3配置文件参数汇总

    - `hibernate.default_batch_fetch_size`:设置默认的批量获取大小,优化关联查询的效率。通常建议的值是4、8或16。 - `hibernate.default_entity_mode`:定义实体的默认表示方式,比如使用POJOs(Plain Old Java ...

    优化Hibernate性能的几点建议

    ### 优化Hibernate性能的几点建议 #### 一、概述 Hibernate作为Java开发中非常流行的ORM(对象关系映射)框架之一,在实现Java...开发者应该根据具体的应用场景和需求,采取合适的优化措施,以达到最佳的性能效果。

    hibernate学习总结

    - 使用`batch-size`设置批量插入、更新的大小。 - `flushMode`控制何时与数据库同步数据。 - `hibernate.show_sql`开启SQL日志,便于调试。 ### 9. Criteria与Querydsl结合 Querydsl 是一个强大的查询构造工具,...

    使用Hibernate开发租房系统第12章课件包含代码

    8. 批量操作:学习如何使用Hibernate进行批量插入、更新和删除,以提高效率,例如Session的saveOrUpdateAll()、deleteAll()和flush()方法。 9. 第二级缓存:了解Hibernate的缓存机制,特别是第二级缓存,它可以提高...

    hibernate代码优化基于配置的多表查询

    例如,使用`Session.flush()`和`Session.clear()`控制事务边界,或配置`hibernate.jdbc.batch_size`来批量插入、更新和删除数据。 7. **避免N+1查询问题**: 当遍历一个集合并访问其关联属性时,可能会触发多次...

    hibernate.cfg.xml文件详细解释

    - `batch_size`:批量处理时每次提交的数据量,增大可减少网络交互,但需考虑内存限制。 - `use_scrollable_resultset`:是否启用可滚动的结果集,适合于分页查询场景。 ##### 4. 字符编码配置 ```xml ...

    hibernate缓存

    3. **非严格读写(Nonstrict Read/Write)**:在读写的基础上,对数据一致性要求较低,适用于更新不频繁的场景。 4. **事务(Transaction)**:只有在同一事务内有效,跨事务会失效。 #### 四、缓存配置与实现 ...

    hibernate配置详解

    如果开启,Hibernate会按照主键顺序排序更新操作,以降低并发环境下的死锁风险。 10. **hibernate.generate_statistics** 开启后,Hibernate会收集性能统计信息,有助于优化应用。 11. **hibernate.use_...

    hibernate.jar包

    - 批量操作:使用批处理更新和插入,提高性能。 6. Hibernate的局限性: - 对SQL的灵活性限制:Hibernate的HQL虽然强大,但在复杂的SQL查询方面仍不如原生SQL。 - 学习曲线:对于初学者,理解ORM的概念和...

    Hibernate问题解决

    Hibernate批量删除和更新 - **批量删除的实现方式:** - **Hibernate方式:** - 使用HQL执行批量操作,例如删除所有名称为“update”的记录: ```java Transaction tx = session.beginTransaction(); long...

    hibernate 持久层优化

    - **`getHibernateTemplate().saveOrUpdateAll`**:对于批量的保存或更新操作非常有效。 - **`getHibernateTemplate().delete`**:适用于单个实体的删除操作,批量删除时效率不高。 - **`getHibernateTemplate()....

    Hibernate配置

    - **作用**:启用后可以提高批量更新的效率,同时确保版本数据的一致性。 ##### 4. **hibernate.jdbc.factory_class** - **用途**:指定自定义的Batcher类。 - **取值**:具体的Batcher实现类名。 - **作用**:...

    hibernate性能:性能、规模、风险 初评

    3. **批量处理**:Hibernate支持批量更新、批量插入等操作,这些批量操作可以显著减少与数据库的交互次数,提高执行效率。 4. **查询优化**:Hibernate提供多种查询方式,如HQL(Hibernate Query Language)、...

Global site tag (gtag.js) - Google Analytics