`

Hibernate的优化方案

 
阅读更多

一、批量修改和删除

  在Hibernate 2中,如果需要对任何数据进行修改和删除操作,都需要先执行查询操作,在得到要修改或者删除的数据后,再对该数据进行相应的操作处理。在数据量少的情况下采用这种处理方式没有问题,但需要处理大量数据的时候就可能存在以下的问题:

   占用大量的内存

   需要多次执行update/delete语句,而每次执行只能处理一条数据。

  以上两个问题的出现会严重影响系统的性能。因此,在Hibernate 3中引入了用于批量更新或者删除数据的HQL语句。这样,开发人员就可以一次更新或者删除多条记录,而不用每次都一个一个地修改或者删除记录了。

  如果要删除所有的User对象(也就是User对象所对应表中的记录),则可以直接使用下面的HQL语句:

  delete User

  而在执行这个HQL语句时,需要调用Query对象的executeUpdate()方法,具体的实例如下所示:

  String HQL="delete User";

  Query query=session.createQuery(HQL);

  int size=query.executeUpdate();

  采用这种方式进行数据的修改和删除时与直接使用JDBC的方式在性能上相差无几,是推荐使用的正确方法。

  如果不能采用HQL语句进行大量数据的修改,也就是说只能使用取出再修改的方式时,也会遇到批量插入时的内存溢出问题,所以也要采用上面所提供的处理方法来进行类似的处理。

  二、 使用SQL执行批量操作

  在进行批量插入、修改和删除操作时,直接使用JDBC来执行原生态的SQL语句无疑会获得最佳的性能,这是因为在处理的过程中省略或者简化了以下处理内容:

  ● HQL语句到SQL语句的转换。

  ● Java对象的初始化。

  ● Java对象的缓存处理。

  但是在直接使用JDBC执行SQL语句时,有一个最重要的问题就是要处理缓存中的Java对象。因为通过这种底层方式对数据的修改将不能通知缓存去进行相应的更新操作,以保证缓存中的对象与数据库中的数据是一致的。

  三、 提升数据库查询的性能

  数据库查询性能的提升也是涉及到开发中的各个阶段,在开发中选用正确的查询方法无疑是最基础也最简单的。

  1 、SQL语句的优化

  使用正确的SQL语句可以在很大程度上提高系统的查询性能。获得同样数据而采用不同方式的SQL语句在性能上的差距可能是十分巨大的。

  由于Hibernate是对JDBC的封装,SQL语句的产生都是动态由Hibernate自动完成的。Hibernate产生SQL语句的方式有两种:一种是通过开发人员编写的HQL语句来生成,另一种是依据开发人员对关联对象的访问来自动生成相应的SQL语句。

  至于使用什么样的SQL语句可以获得更好的性能要依据数据库的结构以及所要获取数据的具体情况来进行处理。在确定了所要执行的SQL语句后,可以通过以下三个方面来影响Hibernate所生成的SQL语句:

   HQL语句的书写方法。

   查询时所使用的查询方法。

   对象关联时所使用的抓取策略。

  2 、使用正确的查询方法

  在前面已经介绍过,执行数据查询功能的基本方法有两种:一种是得到单个持久化对象的get()方法和load()方法,另一种是Query对象的list()方法和iterator()方法。在开发中应该依据不同的情况选用正确的方法。

   get()方法和load()方法的区别在于对二级缓存的使用上。load()方法会使用二级缓存,而get()方法在一级缓存没有找到的情况下会直接 查询数据库,不会去二级缓存中查找。在使用中,对使用了二级缓存的对象进行查询时最好使用load()方法,以充分利用二级缓存来提高检索的效率。

  list()方法和iterator()方法之间的区别可以从以下几个方面来进行比较。

   执行的查询不同

   list()方法在执行时,是直接运行查询结果所需要的查询语句,而iterator()方法则是先执行得到对象ID的查询,然后再根据每个ID值去取 得所要查询的对象。因此,对于list()方式的查询通常只会执行一个SQL语句,而对于iterator()方法的查询则可能需要执行N+1条SQL语 句(N为结果集中的记录数)。

  iterator()方法只是可能执行N+1条数据,具体执行SQL语句的数量取决于缓存的情况以及对结果集的访问情况。

   缓存的使用

  list()方法只能使用二级缓存中的查询缓存,而无法使用二级缓存对单个对象的缓存(但是会把查询出的对象放入二级缓存中)。所以,除非重复执行相同的查询操作,否则无法利用缓存的机制来提高查询的效率。

  iterator()方法则可以充分利用二级缓存,在根据ID检索对象的时候会首先到缓存中查找,只有在找不到的情况下才会执行相应的查询语句。所以,缓存中对象的存在与否会影响到SQL语句的执行数量。

   对于结果集的处理方法不同

  list()方法会一次获得所有的结果集对象,而且它会依据查询的结果初始化所有的结果集对象。这在结果集非常大的时候必然会占据非常多的内存,甚至会造成内存溢出情况的发生。

   iterator()方法在执行时不会一次初始化所有的对象,而是根据对结果集的访问情况来初始化对象。因此在访问中可以控制缓存中对象的数量,以避免 占用过多缓存,导致内存溢出情况的发生。使用iterator()方法的另外一个好处是,如果只需要结果集中的部分记录,那么没有被用到的结果对象根本不 会被初始化。所以,对结果集的访问情况也是调用iterator()方法时执行数据库SQL语句多少的一个因素。

  所以,在使用Query对象执行数据查询时应该从以上几个方面去考虑使用何种方法来执行数据库的查询操作。

  四、 使用正确的抓取策略

  所谓抓取策略(fetching strategy)是指当应用程序需要利用关联关系进行对象获取的时候,Hibernate获取关联对象的策略。抓取策略可以在O/R映射的元数据中声明,也可以在特定的HQL或条件查询中声明。

  Hibernate 3定义了以下几种抓取策略。

   连接抓取(Join fetching)

  连接抓取是指Hibernate在获得关联对象时会在SELECT语句中使用外连接的方式来获得关联对象。

   查询抓取(Select fetching)

  查询抓取是指Hibernate通过另外一条SELECT语句来抓取当前对象的关联对象的方式。这也是通过外键的方式来执行数据库的查询。与连接抓取的区别在于,通常情况下这个SELECT语句不是立即执行的,而是在访问到关联对象的时候才会执行。

   子查询抓取(Subselect fetching)

  子查询抓取也是指Hibernate通过另外一条SELECT语句来抓取当前对象的关联对象的方式。与查询抓取的区别在于它所采用的SELECT语句的方式为子查询,而不是通过外连接。

   批量抓取(Batch fetching)

  批量抓取是对查询抓取的优化,它会依据主键或者外键的列表来通过单条SELECT语句实现管理对象的批量抓取。

  以上介绍的是Hibernate 3所提供的抓取策略,也就是抓取关联对象的手段。为了提升系统的性能,在抓取关联对象的时机上,还有以下一些选择。

   立即抓取(Immediate fetching)

  立即抓取是指宿主对象被加载时,它所关联的对象也会被立即加载。

   延迟集合抓取(Lazy collection fetching)

  延迟集合抓取是指在加载宿主对象时,并不立即加载它所关联的对象,而是到应用程序访问关联对象的时候才抓取关联对象。这是集合关联对象的默认行为。

   延迟代理抓取(Lazy proxy fetching)

  延迟代理抓取是指在返回单值关联对象的情况下,并不在对其进行get操作时抓取,而是直到调用其某个方法的时候才会抓取这个对象。

   延迟属性加载(Lazy attribute fetching)

  延迟属性加载是指在关联对象被访问的时候才进行关联对象的抓取。

  介绍了Hibernate所提供的关联对象的抓取方法和抓取时机,这两个方面的因素都会影响Hibernate的抓取行为,最重要的是要清楚这两方面的影响是不同的,不要将这两个因素混淆,在开发中要结合实际情况选用正确的抓取策略和合适的抓取时机。

  抓取时机的选择

  在Hibernate 3中,对于集合类型的关联在默认情况下会使用延迟集合加载的抓取时机,而对于返回单值类型的关联在默认情况下会使用延迟代理抓取的抓取时机。

   对于立即抓取在开发中很少被用到,因为这很可能会造成不必要的数据库操作,从而影响系统的性能。当宿主对象和关联对象总是被同时访问的时候才有可能会用 到这种抓取时机。另外,使用立即连接抓取可以通过外连接来减少查询SQL语句的数量,所以,也会在某些特殊的情况下使用。

  然而,延迟加载又会面临另外一个问题,如果在Session关闭前关联对象没有被实例化,那么在访问关联对象的时候就会抛出异常。处理的方法就是在事务提交之前就完成对关联对象的访问。

  所以,在通常情况下都会使用延迟的方式来抓取关联的对象。因为每个立即抓取都会导致关联对象的立即实例化,太多的立即抓取关联会导致大量的对象被实例化,从而占用过多的内存资源。

  抓取策略的选取

  对于抓取策略的选取将影响到抓取关联对象的方式,也就是抓取关联对象时所执行的SQL语句。这就要根据实际的业务需求、数据的数量以及数据库的结构来进行选择了。

  在这里需要注意的是,通常情况下都会在执行查询的时候针对每个查询来指定对其合适的抓取策略。指定抓取策略的方法如下所示:

  User user = (User) session.createCriteria(User.class)

  .setFetchMode("permissions", FetchMode.JOIN)

  .add( Restrictions.idEq(userId) )

  .uniqueResult();

  五、 查询性能提升小结

  在本小节中介绍了查询性能提升的方法,关键是如何通过优化SQL语句来提升系统的查询性能。查询方法和抓取策略的影响也是通过执行查询方式和SQL语句的多少来改变系统的性能的。这些都属于开发人员所应该掌握的基本技能,避免由于开发不当而导致系统性能的低下。

   在性能调整中,除了前面介绍的执行SQL语句的因素外,对于缓存的使用也会影响系统的性能。通常来说,缓存的使用会增加系统查询的性能,而降低系统增 加、修改和删除操作的性能(因为要进行缓存的同步处理)。所以,开发人员应该能够正确地使用有效的缓存来提高数据查询的性能,而要避免滥用缓存而导致的系 统性能变低。在采用缓存的时候也应该注意调整自己的检索策略和查询方法,这三者配合起来才可以达到最优的性能。

  另外,事务的使用策略也会影响到系统的性能。选取正确的事务隔离级别以及使

转自:http://tech.it168.com/a2009/0311/268/000000268144.shtml

分享到:
评论

相关推荐

    Hibernate优化方案

    Hibernate优化方案。内附hibernate的优化

    hibernate 优化方案

    hibernate 的优化方案,很不错,通俗易懂

    hibernate性能优化方案

    设计好的hibernate与设计不好的hibernate性能差别巨大,如何改善hibernate的性能是合理使用hibernate的关键

    Hibernate3性能优化方案

    Hibernate3性能优化Hibernate3性能优化Hibernate3性能优化Hibernate3性能优化

    基于Hibernate的在线考试优化设计与实现

    现有的基于Web的在线考试存在的问题是,当大量用户同时提交试卷时,服务器却无法承载过多用户,这将导致系统的不稳定。Hibernate是连接Java对象模型和关系...本文针对在线考试系统存在的问题,设计并实现了性能优化方案。

    系统优化方案.docx

    系统调优方向有以下几种: 数据库调参、Tomcat调参、Hibernate调参、数据库字段调优、Sql语句调优、线程调优、代码调优、服务器调优。

    如何提高hibernate性能

    Hibernate的orm映射固然方便,但是数据达到一定量时,也会遇到一些瓶颈,这时hibernate的优化就显得异常重要,本文档含有多种方式的优化方案,方便的h话你可以关注一下!

    maven+springmvc+spring+hibernate+freemarker

    freemarker也有优化,参考common包下。对日期工具类有各种情况的代码说明。参考utils下的DateUtils.java类。 slf4j日志文件有详细的配置。另外还有几个小例子可以试运行下。有什么问题都可以沟通讨论。 欢迎大家讨论...

    Struts+Spring+Hibernate(CRUD操作案例)-分页查询

    前段时间时间当我在学习SSH框架技术的时候,在网上很难找到关于SSH的...该项目我进行多次的代码优化!也为我以后的项目提供模板。如您对项目有异议或更好的解决方案!请与我联系!共同探讨解决!也共同进步!在此感谢!

    java轻量级的CMS解决方案-天梯.zip

    资源优化: 方案在设计时考虑了可用资源,以最大化其效用。通过明智的资源分配,方案可以在有限的资源条件下实现最大的效益,提高效率并减少浪费。 风险管理: 方案通常会对潜在的风险进行评估,并制定相应的风险...

    Struts+Spring+Hibernate(CRUD操作案例)-分页查询-作者:llfzy

    前段时间时间当我在学习SSH框架技术的时候,在网上很难找到关于SSH...该项目我进行多次的代码优化!也为我以后的项目提供模板。如您对项目有异议或更好的解决方案!请与我联系!共同探讨解决!也共同进步!在此感谢!!

    Hibernate_Annotation关联映射

    这种方案不会得到什么明显的优化,而且还会增加一些附加的UPDATE语句。 单向: 通过在被拥有的实体端(owned entity)增加一个外键列来实现一对多单向关联是很少见的,也是不推荐的,建议通过一个联接表来实现这种...

    一个用struts+spring+hibernate编写的bbs源码

    2、支持多数据库:天乙社区6.0采用了Hibernate作为数据库持久化的解决方案,支持DB2、PostgreSQL、MySQL、Oracle、Sybase、Microsoft SQL Server、SAP DB、Informix、HypersonicSQL、Ingres、Progress、Mckoi SQL、...

    java_jsp项目源码_移动ssh项目(struts+spring+hibernate+oracle)130222.rar

    移动SSH项目(Struts + Spring + Hibernate + Oracle)是一个基于Java Web技术栈的企业级应用,旨在为企业提供一个高效、灵活且可扩展的解决方案。项目采用了Struts2作为表现层框架,Spring作为依赖注入和管理的核心...

    java_jsp项目源码_网上订餐系统(struts+spring+hibernate).rar

    本项目是一个基于Struts、Spring和Hibernate框架的网上订餐系统,旨在为餐厅提供一个高效、便捷的在线订餐解决方案。系统支持多种餐厅管理功能,如菜品分类、菜品信息管理、订单处理、顾客反馈等。同时,系统还提供...

    java_jsp项目源码_图书管理系统(struts+hibernate+spring)130225.rar

    本项目是一个基于Struts、Hibernate和Spring框架的图书管理系统,旨在为图书馆提供一个高效、灵活且易于维护的解决方案。系统支持图书的增删改查功能,以及借阅、归还、续借等借阅管理功能。同时,系统还提供了用户...

    java_jsp项目源码_网上书店(struts+hibernate+css+mysql)130223.rar

    **项目名称:** 网上书店管理系统 **项目简介:** 本项目是一个基于Java技术栈的网上书店管理系统...总之,本项目是一个功能完善、易于维护和扩展的网上书店管理系统,可以为客户提供稳定、高效的在线销售解决方案。

    IT开发方面的视频教程以及案例视频

    统-Hibernate 部分 Spring 实战:使用 SSH 框架技术开 发学籍管理系统 Struts 实战:使用 SSH 框架技术开 发学籍管理系统 WebGL 之3D 引擎 Three.js 基础与 项目实战 方案:如何操作 WORD 文件 方案:如何破解 ACCESS...

    java_jsp项目源码_OA办公自动化管理系统(Struts1.2+Hibernate3.0+Spring2+DWR).rar

    OA办公自动化管理系统是一款基于Struts1.2、Hibernate3.0、Spring2和DWR的综合性企业级应用解决方案,旨在帮助企业实现高效、便捷的办公管理。该系统具备以下功能: 1. 用户管理:支持用户注册、登录、权限分配、...

    网站设计方案(完整版).doc

    XXX公司 XX发布平台 设计方案 XX单位 2022年12月 1、概述 阐述项目建设背景…… 项目必要性、先进性…… 2、建设目标 1、宣传公司、中心的管理理念,促进企业文化的建设与传播; 2、实现对外信息发布的信息资源分类...

Global site tag (gtag.js) - Google Analytics