- 浏览: 1008009 次
- 性别:
- 来自: 广州
文章分类
- 全部博客 (394)
- OSGI (14)
- 多线程 (10)
- 数据库 (30)
- J2ME (1)
- JAVA基础知识 (46)
- 引用包 (1)
- 设计模式 (7)
- 工作流 (2)
- Ubuntu (7)
- 搜索引擎 (6)
- QT (2)
- Ubuntu下编程 (1)
- 小程序 (2)
- UML (1)
- Servlet (10)
- spring (16)
- IM (12)
- 文档视频转为flash格式在线播放 (19)
- Maven (8)
- 远程调用 (2)
- PHPRPC (1)
- EXTJS学习 (2)
- Hibernate (16)
- 技术文章 (38)
- flex (5)
- 海量数据处理 (5)
- FTP (8)
- JS (10)
- Struts (1)
- hibernate search (13)
- JQuery (2)
- EMail (3)
- 算法 (4)
- SVN (7)
- JFreeChart (4)
- 面试 (4)
- 正规表达式 (2)
- 数据库性能优化 (10)
- JVM (6)
- Http Session Cookie (7)
- 网络 (12)
- Hadoop (2)
- 性能 (1)
最新评论
-
hy1235366:
能够随便也发一下,你退火算法程序使用的DistanceMatr ...
模拟退火算法总结(含例子)(转) -
梅强强:
感谢分享。。帮大忙了
swftools转换文件时线程堵塞问题的解决方法 -
wenlongsust:
openoffice和文件不在同一个服务器上,用过吗?
[JODConverter]word转pdf心得分享(转) -
2047699523:
如何在java Web项目中开发WebService接口htt ...
利用Java编写简单的WebService实例 -
abingpow:
唉,看起来好像很详细很不错的样子,可惜不是篇面向初学者的文章, ...
Spring与OSGi的整合(二)(转)
hibernate性能优化
由于hibernate是对jdbc的一个封装,而且在session的缓存中存在着相互关联的对象。对于一个类的访问将导致对另外一个关联类的访问,这样将导致大量的sql语句产生,所以为了提升hibernate性能减少频繁访问数据库,就需要对hibernate进行优化。
我们知道在hibernate的默认情况下,比如:在一对多的情况下,当我们访问Customer类后,又同时访问它相关联的Order类,但是如果我们不需要order的信息呢?这将导致hibernate的性能下降。
怎么解决呢?下面我们看一下hibernate加载一个对象的方式有哪些?
1.立即加载
所谓立即加载,就是指当加载完实体对象后,立即加载其关联的对象数据,在Customer.hbm.xml里的内容为:
<set name="order" table="ord" cascade="all" lazy="false" inverse="true">
<key column="c_id"/>
<one-to-many class="com.lovo.Order"></one-to-many>
</set>
-------------------
从运行的结果中我们可以看出hibernate连续调用了两次sql,分别完成了对Customer和order对象的加载,这就是立即加载的基本原理,上面配置里面cascade="all"表示当我增删改这个实体时是不是要对相关联的实体进行增删改操作,在一般情况下用delete-update,lazy="false"表示立即加载这个对象,inverse="true"表示在一对多的情况下,把对象的加载交给多的一方进行维护。就好比zf和我们,zf不可能可照顾所有的人吧,得让我们自己照顾自己。呵呵,这个举例只是好理解而已。
2.延迟加载
当hibernate加载Customer对象时同时加载了关联的order对象,如果只需要读取Customer对象的信息而不需要读取order类的信息的话将会导致性能损耗,hibernate引入了延迟加载的方式避免了这一问题,
<set name="order" table="ord" cascade="all" lazy="true" inverse="true"><!--hibernate默认情况也是true-->
<key column="c_id"/>
<one-to-many class="com.lovo.Order"></one-to-many>
</set>
与立即加载不同之处在于,hibernate没有在加载Customer对象时就加载order对象并读取对象的信息,而是在调用customer.order.size()才会读取order的信息,这就是延迟加载的机制,当真正需要访问关联对象才执行sql语句进行数据读取。
3.预加载
所谓预加载就是指通过外连接(out-join)来获得对象的关联实例;
比如:Query query = session.createQuery("from Customer c left join c.order");
运行上面代码,hibernate会生成一条sql语句,相对于立即加载情况下的读取多条sql语句,预加载方式在性能上带来了更多的提升,减少了对数据库的访问次数,但是,我们发现预加载的情况下,关联对象的实例也会被创建。所以,这也是一种不推荐的加载方式,应当尽量使用延迟加载方式。
4.批量加载
hibernate中的批量加载就是批量提交多个限定条件,一次完成多个数据的读取,例如:
from Customer where c_id=1;
from Customer where c_id=2;
我们可以将其整合为一条语句:
from Customer where c_id in(1,2);
在hibernate的关联关系中,我们可以在立即加载和延迟加载里设定批量加载的数目,从而减少查询语句的数目,提高延迟加载和立即加载的性能。在映射文件中<set>元素的batch-size属性用于设置批量加载的数量,Customer类的映射文件有如下:
<set name="order" table="ord" cascade="all" lazy="true" inverse="true" batch-size="10"><!--一般小于10-->
<key column="c_id"/>
<one-to-many class="com.lovo.Order"></one-to-many>
</set>
可以发现在使用批量加载的情况下,select语句使用了in关键字来限定范围,从而减少了select语句的使用,而in所限定的范围大小与"batch-size"属性的值有关,值越小范围就越小,反之越大,一般来说batch-size属性设置为一个小于10的数值,由此可见,批量加载的方式可以成为延迟加载或立即加载的一种优化解决方案,采用这种方式抓取对象又被称为批量抓取(Batch fetching);
hibernate查询优化:
我们已经理解了hibernate中对象加载方式后,可以看出在hibernate中主要有如下几个方面来优化查询性能:
1.降低数据库的访问的次数和频率,减少select语句的数量,对延迟加载和立即加载设置批量抓取策略。
2.使用延迟加载,避免不需要的多余数据,
3.使用投影查询,避免查询数据占用缓存。
4.减少访问字段,降低访问数据库的数据量,利用query()对象的iterate()方法
query的list()和iterator方法都可以执行HQL查询语句,但是list()方法会直接操作sql访问数库,而iterator方法会根据主键字段到一、二级缓存里查找,如果有就加入到查询结果中,没有就执行额外的查询语句。
Query q1=session.createQuery("from Customer");
List it1=q1.list();
Query q2=session.createQuery("from Customer");
List it2=q2.iterate();
list()方法查询所有字段信息,而iterate()方法查询的却不是所有字段而是c_id,也就是说减少了访问字段,同时iterator()方法根据c_id再向缓存里进行查找对象,如果缓存里没有数据最后再进行数据库的访问。
hibernate缓存:
hibernate为什么要有缓存呢??和其它关系型数据库一样,
我们不可能每次相同的查询都去与数据库进行交互吧,也就是说hibernate的缓存就是一块内在空间,充当数据库在内存中的一个临时容器,当我们每次执行session.load(),save().update()时,或者query.list(),iterate()方法时,如果在Sesssion中不存在相应对象,hibernate就把该对象加入到缓存中。比如:我们查询ID为了的用户,由于第一次在缓存中没有,就与数据库进行交互,并且加入到一级缓存中,第二次呢?由于一级缓存中已经存在了,所以直接从一级缓存中获取数据,提高了查询性能。
缓存分为以下几种:
1。一级缓存:必须的,缓存中每个持久对象都对应一个OID,用clear()清除对象.
2.二级缓存:是一个处理分布式的缓存。不是必须的。在查询时首行是从一级缓存中查找,如果没有就去二级缓存中查找,二级缓存最大的好处在于提高了查询性能,但是,hibernate并没有提供二级缓存的实现,而是为第三方的缓存组件提供了接口,所以还需要配置。
3.查询缓存:使用查询缓存,如果查询结果集中包含实体,二级缓存中只会存放实体OID,如果查询部分属性,则二级缓存会存放所有属性值。hibernate默认是不进行查询缓存的。如果要进行缓存,需要调用Query.setCacheable(true)方法。
Session管理:
首先,什么是线程安全,什么是线程不安全??
线程安全:就是说可以有多个线程同时访问,
线程不安全:不能有多个线程访问。否则,会造成混乱。
在Session管理中SessionFacory是线程安全,它可以被多个线程同时访问,而Session是不安全的,以前我们是在每个方法里都会使用一个session,这样造成的结果是Session的频繁创建和销毁,内在消耗也相应增大了。在Session管理中,可以使用ThreadLocal模式,它为多线程的情况下并发访问问题提供了一种隔离机制,例如:
public static Session getSession(){
Session session=(Session)threadLocal.get();//获得session对象
if(session==null){
session = SessionFactory.openSession();
threadLocal.set(session);
}
return session;
}
ThreadLocal的使用将使得我们在线程级进行Session重用,从而充分利用一缓存中的已有的数据,避免数据库访问开销的浪费和大量临时对象的反复创建。
hibernate的批量处理:加入10000条数据
PrepareStatement pst = conn.preparedStatement(...);
for(int i=0;i<10000;i++){
pst.addBatch();
}
int[] count=pre.executeBatch();
由于会产生大量的对象存放在内存中,所以性能不好
<script type="text/javascript"><!--
google_ad_client = "pub-1076724771190722";
/* JE个人博客468x60 */
google_ad_slot = "5506163105";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
</script><script src="http://pagead2.googlesyndication.com/pagead/js/r20101117/r20101214/show_ads_impl.js"></script><script src="http://pagead2.googlesyndication.com/pagead/expansion_embed.js"></script><script src="http://googleads.g.doubleclick.net/pagead/test_domain.js"></script><script src="http://pagead2.googlesyndication.com/pagead/render_ads.js"></script><script>google_protectAndRun("render_ads.js::google_render_ad", google_handleError, google_render_ad);</script>
由于hibernate是对jdbc的一个封装,而且在session的缓存中存在着相互关联的对象。对于一个类的访问将导致对另外一个关联类的访问,这样将导致大量的sql语句产生,所以为了提升hibernate性能减少频繁访问数据库,就需要对hibernate进行优化。
我们知道在hibernate的默认情况下,比如:在一对多的情况下,当我们访问Customer类后,又同时访问它相关联的Order类,但是如果我们不需要order的信息呢?这将导致hibernate的性能下降。
怎么解决呢?下面我们看一下hibernate加载一个对象的方式有哪些?
1.立即加载
所谓立即加载,就是指当加载完实体对象后,立即加载其关联的对象数据,在Customer.hbm.xml里的内容为:
<set name="order" table="ord" cascade="all" lazy="false" inverse="true">
<key column="c_id"/>
<one-to-many class="com.lovo.Order"></one-to-many>
</set>
-------------------
从运行的结果中我们可以看出hibernate连续调用了两次sql,分别完成了对Customer和order对象的加载,这就是立即加载的基本原理,上面配置里面cascade="all"表示当我增删改这个实体时是不是要对相关联的实体进行增删改操作,在一般情况下用delete-update,lazy="false"表示立即加载这个对象,inverse="true"表示在一对多的情况下,把对象的加载交给多的一方进行维护。就好比zf和我们,zf不可能可照顾所有的人吧,得让我们自己照顾自己。呵呵,这个举例只是好理解而已。
2.延迟加载
当hibernate加载Customer对象时同时加载了关联的order对象,如果只需要读取Customer对象的信息而不需要读取order类的信息的话将会导致性能损耗,hibernate引入了延迟加载的方式避免了这一问题,
<set name="order" table="ord" cascade="all" lazy="true" inverse="true"><!--hibernate默认情况也是true-->
<key column="c_id"/>
<one-to-many class="com.lovo.Order"></one-to-many>
</set>
与立即加载不同之处在于,hibernate没有在加载Customer对象时就加载order对象并读取对象的信息,而是在调用customer.order.size()才会读取order的信息,这就是延迟加载的机制,当真正需要访问关联对象才执行sql语句进行数据读取。
3.预加载
所谓预加载就是指通过外连接(out-join)来获得对象的关联实例;
比如:Query query = session.createQuery("from Customer c left join c.order");
运行上面代码,hibernate会生成一条sql语句,相对于立即加载情况下的读取多条sql语句,预加载方式在性能上带来了更多的提升,减少了对数据库的访问次数,但是,我们发现预加载的情况下,关联对象的实例也会被创建。所以,这也是一种不推荐的加载方式,应当尽量使用延迟加载方式。
4.批量加载
hibernate中的批量加载就是批量提交多个限定条件,一次完成多个数据的读取,例如:
from Customer where c_id=1;
from Customer where c_id=2;
我们可以将其整合为一条语句:
from Customer where c_id in(1,2);
在hibernate的关联关系中,我们可以在立即加载和延迟加载里设定批量加载的数目,从而减少查询语句的数目,提高延迟加载和立即加载的性能。在映射文件中<set>元素的batch-size属性用于设置批量加载的数量,Customer类的映射文件有如下:
<set name="order" table="ord" cascade="all" lazy="true" inverse="true" batch-size="10"><!--一般小于10-->
<key column="c_id"/>
<one-to-many class="com.lovo.Order"></one-to-many>
</set>
可以发现在使用批量加载的情况下,select语句使用了in关键字来限定范围,从而减少了select语句的使用,而in所限定的范围大小与"batch-size"属性的值有关,值越小范围就越小,反之越大,一般来说batch-size属性设置为一个小于10的数值,由此可见,批量加载的方式可以成为延迟加载或立即加载的一种优化解决方案,采用这种方式抓取对象又被称为批量抓取(Batch fetching);
hibernate查询优化:
我们已经理解了hibernate中对象加载方式后,可以看出在hibernate中主要有如下几个方面来优化查询性能:
1.降低数据库的访问的次数和频率,减少select语句的数量,对延迟加载和立即加载设置批量抓取策略。
2.使用延迟加载,避免不需要的多余数据,
3.使用投影查询,避免查询数据占用缓存。
4.减少访问字段,降低访问数据库的数据量,利用query()对象的iterate()方法
query的list()和iterator方法都可以执行HQL查询语句,但是list()方法会直接操作sql访问数库,而iterator方法会根据主键字段到一、二级缓存里查找,如果有就加入到查询结果中,没有就执行额外的查询语句。
Query q1=session.createQuery("from Customer");
List it1=q1.list();
Query q2=session.createQuery("from Customer");
List it2=q2.iterate();
list()方法查询所有字段信息,而iterate()方法查询的却不是所有字段而是c_id,也就是说减少了访问字段,同时iterator()方法根据c_id再向缓存里进行查找对象,如果缓存里没有数据最后再进行数据库的访问。
hibernate缓存:
hibernate为什么要有缓存呢??和其它关系型数据库一样,
我们不可能每次相同的查询都去与数据库进行交互吧,也就是说hibernate的缓存就是一块内在空间,充当数据库在内存中的一个临时容器,当我们每次执行session.load(),save().update()时,或者query.list(),iterate()方法时,如果在Sesssion中不存在相应对象,hibernate就把该对象加入到缓存中。比如:我们查询ID为了的用户,由于第一次在缓存中没有,就与数据库进行交互,并且加入到一级缓存中,第二次呢?由于一级缓存中已经存在了,所以直接从一级缓存中获取数据,提高了查询性能。
缓存分为以下几种:
1。一级缓存:必须的,缓存中每个持久对象都对应一个OID,用clear()清除对象.
2.二级缓存:是一个处理分布式的缓存。不是必须的。在查询时首行是从一级缓存中查找,如果没有就去二级缓存中查找,二级缓存最大的好处在于提高了查询性能,但是,hibernate并没有提供二级缓存的实现,而是为第三方的缓存组件提供了接口,所以还需要配置。
3.查询缓存:使用查询缓存,如果查询结果集中包含实体,二级缓存中只会存放实体OID,如果查询部分属性,则二级缓存会存放所有属性值。hibernate默认是不进行查询缓存的。如果要进行缓存,需要调用Query.setCacheable(true)方法。
Session管理:
首先,什么是线程安全,什么是线程不安全??
线程安全:就是说可以有多个线程同时访问,
线程不安全:不能有多个线程访问。否则,会造成混乱。
在Session管理中SessionFacory是线程安全,它可以被多个线程同时访问,而Session是不安全的,以前我们是在每个方法里都会使用一个session,这样造成的结果是Session的频繁创建和销毁,内在消耗也相应增大了。在Session管理中,可以使用ThreadLocal模式,它为多线程的情况下并发访问问题提供了一种隔离机制,例如:
public static Session getSession(){
Session session=(Session)threadLocal.get();//获得session对象
if(session==null){
session = SessionFactory.openSession();
threadLocal.set(session);
}
return session;
}
ThreadLocal的使用将使得我们在线程级进行Session重用,从而充分利用一缓存中的已有的数据,避免数据库访问开销的浪费和大量临时对象的反复创建。
hibernate的批量处理:加入10000条数据
PrepareStatement pst = conn.preparedStatement(...);
for(int i=0;i<10000;i++){
pst.addBatch();
}
int[] count=pre.executeBatch();
由于会产生大量的对象存放在内存中,所以性能不好
发表评论
-
getHibernateTemplate()和getSession()的区别(转)
2011-04-21 11:07 1074自动生成hibernate配置 ... -
getHibernateTemplate().execute(new HibernateCallback())方法(转)
2011-04-18 15:29 21521. HibernateCallback是一个接口,该接口只有 ... -
Hibernate之查询效率问题(转)
2011-03-24 12:36 1353相信越来越多的web开发者,在持久层都采用了h ... -
hibernate查询表的部分属性
2011-03-09 10:44 1701由于一个表中含有比较占内存的字段,当查询的结果比较大时,可能会 ... -
HQL日期比较需要注意的问题
2011-03-07 22:32 5316如果日期比较格式写成写成如下方式: String hq ... -
异常:Caused by: java.sql.SQLException: Duplicate entry '??' for key 2
2011-02-25 09:39 4011今天将项目部署到RHEL平台时,初始化数据库时出现如下的问题: ... -
异常:could not get table metadata: CONTRACT
2011-02-16 09:33 2567今天开启tomcat(里面发布了J2EE项目)时出现如下异常: ... -
Hibernate中Criteria的完整用法(转)
2011-01-17 17:37 1397最近在项目中使用 Spring 和 Hibernate ... -
hibernate获取记录条数的方法(转)
2011-01-17 16:20 2932hql获取记录条数 String hql = &q ... -
hibernate获取记录行数异常
2011-01-14 16:39 2246使用hibernate时来查询符合条件的记录条数时出现如下的异 ... -
Hibernate的setFirstResult,setMaxResults(转)
2010-12-15 22:05 2133一、query.scroll()和query. ... -
异常Caused by: java.lang.ClassNotFoundException: javax.persistence.Entity
2010-09-16 09:40 4893有时使用hibernate时出现如下的异常: Caused ... -
hibernate-事务管理(转)
2010-09-13 10:14 1380Hibernate 是JDBC 的轻量级 ... -
hibernate单独事务与纳入spring旗下的事务管理方式
2010-09-13 10:07 1503Hibernate要开启事务,然后再进行数据库的操作,最后提交 ... -
Hibernate jar包的作用(转)
2010-09-12 22:16 2810(1)hibernate3.jar:Hibernate ...
相关推荐
### Hibernate性能优化研究 #### 一、引言 随着企业级应用的发展,高效的数据持久化技术成为了提升系统性能的关键因素之一。Hibernate作为一种流行的面向Java环境的对象关系映射(Object-Relational Mapping,简称...
《Hibernate性能优化》 在Java应用开发中,Hibernate作为一个强大的对象关系映射(ORM)框架,极大地简化了数据库操作。然而,如果不进行适当的优化,它可能会成为系统性能的瓶颈。以下是一些关于Hibernate性能优化...
珍藏的hibernate性能优化,如果对hibernate进行优化,很详细,是工作和面试的好助手
### Hibernate性能优化方案详解 #### 一、引言 Hibernate作为Java领域中广泛使用的对象关系映射(ORM)框架,其高效性和灵活性受到众多开发者的青睐。然而,不当的设计和配置往往会导致性能瓶颈,严重影响应用程序...
本文将深入探讨Hibernate性能优化中的一个重要概念——一级缓存,并结合给出的压缩包文件“hibernate_cache_level1”,来详细解析一级缓存的工作原理及其优化策略。 一级缓存是Hibernate内置的一种缓存机制,它存在...
Hibernate 性能优化 在 Hibernate 中,性能优化是非常重要的,因为它直接影响着应用程序的效率和可扩展性。...Hibernate 性能优化需要我们注意批量处理和 1+n 问题,并使用相应的解决方法来避免这些问题。
《Hibernate性能优化共9页.pdf》的压缩包文件聚焦于Java开发中的一个重要框架——Hibernate的性能调优。Hibernate作为一款强大的对象关系映射(ORM)框架,极大地简化了数据库操作,但同时也可能带来性能问题。以下...
在进行大型项目开发时,性能优化是至关重要的,特别是对于基于SSH(Struts、Spring、Hibernate)这样的企业级框架的应用。SSH性能优化主要是针对Struts的MVC处理、Spring的依赖注入以及Hibernate的对象关系映射进行...
本文将深入探讨Hibernate缓存的原理、类型及其对性能优化的影响。 ### Hibernate缓存原理 Hibernate缓存主要分为一级缓存和二级缓存。一级缓存,也称为会话缓存(Session Cache),是默认启用的,由Hibernate自动...
的效率低于直接JDBC存取,然而,在经过比较好的性能优化之后,Hibernate的性能还是让人相当满意的, 特别是应用二级缓存之后,甚至可以获得比较不使用缓存的JDBC更好的性能,下面介绍一些通常的 Hibernate的优化策略...
【标签】:hibernate, 性能优化 【正文】: 1. **数据库设计调整**: - **降低关联的复杂性**:减少多对多关联,避免过度嵌套的对象关系。 - **避免联合主键**:联合主键可能导致额外的性能损失,尝试使用单独的...
以下是对《hibernate性能优化[参考].pdf》内容的详细解读: 1. **数据库优化**: - **物理硬件优化**:关注磁盘的IO性能,因为数据库读写频繁,磁盘的寻道能力直接影响数据访问速度。 - **MySQL配置优化**:通过...
### Hibernate 性能优化 #### 一、引言 Hibernate 是一款非常强大的对象关系映射(ORM)框架,它能够简化 Java 应用程序与数据库之间的交互过程。然而,对于初次接触 Hibernate 的开发者来说,可能会遇到性能方面...
本话题将深入探讨“Hibernate性能测试代码”,以帮助我们理解如何有效地评估和优化Hibernate在实际应用中的表现。 首先,性能测试是软件开发过程中的关键环节,它旨在确定系统的响应时间、吞吐量和资源利用率等指标...
### 优化Hibernate性能的几点建议 #### 一、调整Fetch Size以提高性能 在使用Hibernate进行数据查询时,Fetch Size的设置对性能有着显著的影响。Fetch Size是指每次从数据库中取出的数据行数,默认情况下,Oracle...
二级缓存是Hibernate性能优化的重要手段,通过合理配置和使用,可以显著减少数据库访问,提高系统响应速度。但同时,需要注意缓存的副作用,如数据一致性、并发控制等问题。在实际应用中,需要结合业务场景和性能...