Hibernate性能优化策略(一)

2014-11-24 08:59:15 · 作者: · 浏览: 1
在Hibernate系列文章的第一篇中就提到了使用Hibernate会有一个性能问题,但万事不是绝对的,总会有办法,下面的几个方法虽不能彻底解决性能的问题,但基本上也能满足大多数的需求。
抓取策略
单端代理
a) 保持默认,同fetch="select",如:,fetch="select",另外发送一条select语句加载当前对象的关联对象或集合。
b) 设置fetch="join",如:,hibernate会通过一个select语句连接(内联/外联:取决于外键是否为空)抓取其关联对象或集合,lazy失效,fetch为select或join不影响hql查询,它影响的是load,get方法。
可能会出现N+1问题,如:查询100个学生显示到列表中:首先会发出查询学生的sql语句,然后会发出根据班级id查询班级的sql语句,这样就会导致N+1问题,也就是发出了N+1条语句,会严重影响性能,所以我们可以采用预先抓取的策略,如:selects from Student s join fetch s.classes。
集合代理
a) 保持默认,同fetch="select",如:,fetch="select",另外发送一条select语句加载当前对象的关联对象或集合。
b) 设置fetch="join",如:,hibernate会通过一个select语句连接(内联/外联)抓取其关联对象或集合,fetch="join",那么lazy失效,fetch="join",只影响get和load,对hql没有影响。
c) 设置fetch="subselect",如:,另外发送一条select语句抓取在前面查询到的所有实体的关联集合,fetch="subselect",会影响hql查询。
批量抓取
batch-size属性,可以批量加载实体类,参见参见Classes.hbm.xml中的配置: ,batch-size属性就是为了减少发出的sql语句量。
Lazy加载机制
Lazy是延迟加载,只有真正使用该对象时,才会创建,对于Hibernate来说,只有真正使用时才会发出sql,这样可以提高一些性能。Hibernate的lazyloading采用了一个HibernateSession来管理session,他的逻辑是每进行一次 数据库操作,就开新的session,操作完成后立即关闭该session,这样做的好处是可以严格关闭session,但不适合跨方法的事务。
Class标签上的Lazy
标签上,可以取值:true/false,它只影响普通属性。查id不发sql,因为传的就是主键,查别的属性会发sql,HibernateLazy有效期必须是session在open时才可以,解决方式是使用openSessionInview(后面的Spring会有讲解)。
集合标签上的Lazy
/标签上,可以取值:true/false/extra。标签上的lazy不会影响集合上的lazy特性,把class标签上的lazy设置成false时,再load类时会把普通属性都查出来,但是集合不查。
get集合时不会发sql,迭代会发sql,查个数的时候会把整个集合查出来,这样对效率有影响,lazy在集合上用extra获取size的时候会发出count语句,对效率有所提升。
单端关联上的Lazy
/单端关联标签上,可以取值:false/proxy/noproxy。标签上的lazy不会影响单端关联对象的lazy策略。单端关联上的lazy和集合一样,在get时返回代理不发查询语句,使用时发出sql。在单端关联上lazy=false,在访问普通属性时发出两条sql,查询属性以及对应的关联对象。
作者:StubbornPotatoes