Hibernate在使用中,因为其本身的性能问题,我们经常需要去做hibernate的一些性能优化,以此来提高hibernate的运行性能,具体的手段:
1.优化映射关系 2.尽量减少一些不必要的持久化操作 3.hql的优化 4.使用懒加载来加载数据 5.fetch属性,使用select来做单表查询 6.缓存
...
sql优化:
1.sql语句中不要使用*来替代所有字段
2.所有的sql语句都应该大写
3.需要几个字段,就只查几个字段
4.尽量减少联表查询,子查询等
5.尽量减少调用系统函数
6.当数据量较大时,使用索引来查询
7.sql语句中,尽量避免对索引字段进行一些运算
8.尽量使用>=,<=来替代>,<符号
9.尽量避免在sql中使用all,in,distinct,...这些关键字来完成查询
10.between...and... 和<,>比较,尽量使用btween...and...
11.尽量减少使用否定性的条件,比如!=,<>,not ....
12.sql语句中有多个条件的时候,过滤掉数据最多的条件,一定放在sql的最右边
13.当字段较多或数据量较大时,对表进行切割
其中,hibernate使用中,经常用到缓存来优化。
Hibernate包含缓存功能,其中包括:一级缓存(Session缓存)和二级缓存(SessionFactory缓存)一级缓存开发中不使用。
hibernate中一级缓存的特点:
1.只在一次连接范围内有效,连接关闭,缓存会清空
2.一级缓存只适用于根据主键查对象(get/load方法),对其他查询无效
二级缓存可以使用,因为SessionFactory不会随意销毁,只会在服务器停止时才销毁。
但开发中二级缓存默认是关闭的,需要手工通过配置来打开和使用。
一级缓存只支持按主键查询出的数据(通过get/load方法)。 二级缓存可以支持Session或Query查询出的任何数据。
二级缓存需要第三方支持才可以使用,可以选择:ehcache或oscache来实现缓存功能。这里使用ehcache实现。
主要适合以下数据放入二级缓存:
1. 很少被修改,大量查询的
2. 不是很重要的数据,允许出现偶尔并发访问的
1.配置二级缓存
第一步,添加ehcache依赖,这里添加maven依赖如下:
<dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.10.3</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-ehcache</artifactId> <version>4.3.11.Final</version> </dependency> 第二步,修改hibernate.cfg.xml文件,内容如下:
<!-- 开启二级缓存 --> <property name="cache.use_second_level_cache">true</property> <!--缓存功能提供者--> <propertyname="cache.region.factory_class"> org.hibernate.cache.EhCacheRegionFactory </property> <!--缓存配置文件--> <property name="net.sf.ehcache.configurationResourceName">ehcache.xml</property> <!--开启查询缓存--> <property name="hibernate.cache.use_query_cache">true</property> 第三步,准备ehcache缓存配置文件ehcache.xml文件:
在resources目录下,创建ehcache.xml文件(文件名必须一致),代码如下:
<ehcache> <!-- 表示硬盘上保存缓存的位置。默认是临时文件夹。 --> <diskStore path="java.io.tmpdir"/> <!-- 默认缓存配置,如果类没有做特定的设置,则使用这里配置的缓存属性。 maxElementsInMemory - 设置缓存中允许保存的最大对象(pojo)数量 eternal - 设置对象是否永久保存,如果为true,则缓存中的数据永远不销毁,一直保存。 timeToIdleSeconds - 设置空闲销毁时间。 只有eternal为false时才起作用。表示从现在到上次访问时间如果超过这个值,则缓存数据销毁 timeToLiveSeconds - 设置活动销毁时间。表示从现在到缓存创建时间如果超过这个值,则缓存自动销毁 overflowToDisk - 设置是否在超过保存数量时,将超出的部分保存到硬盘上。 --> <defaultCache maxElementsInMemory="1500" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="300" overflowToDisk="true" /> <!-- 也可以通过name设置针对某个类的缓存配置 <cache name="cn.sz.gl.pojo.Emp" maxElementsInMemory="1000" eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="false" /> --> </ehcache> 第四步,在要缓存的实体映射文件中(比如这里的Emp.java文件),添加缓存方式。
在实体类映射文件(比如Emp.hbm.xml)中的class标签里面,加上如下代码:
<cache usage="read-only"/>
其中,对于usage的取值:
1.read-only:只读缓存,缓存的数据只能读取不能修改,使用该缓存后,对应表中的数据不允许再通过hibernate进行增,删,改操作,只能查询。
一般只用在不修改的数据上,例如:省份,城市表
优点:性能高;
2.read-write:可读写缓存,缓存中的数据会随着数据库的修改而一起修改。
所有普通的表都可以使用此缓存
优点:数据可以读写,准确度高
3.nonstrict-read-write:不严格的可读写缓存,缓存中的数据会随着数据库修改而变化,但不立刻改变。经过一定时间后,缓存的数据才会与数据库同步。
优点:性能比可读写缓存要高,但准确度低
使用范围:对于一些准确度要求不高的表数据,可以使用,例如:新闻表
4.transactional:支持事务处理的缓存,缓存也可以随着数据库的提交和回滚一起提交回滚。现在read-write也支持此功能,因此该形式已经被取消
至此,hibernate缓存配置完成,另外,如果想让Query也支持缓存查询,需要在查询前加入一行设置缓存查询的代码