您的位置:首页 > 其它

Hibernate性能调优

2012-08-31 17:01 453 查看
Hibernate性能调优
1 Hibernate 连接池

hibernate自带一个连接池,但是这个连接池的性能不好,BUG也比较多,所以hibernate借助第三方的连接池来配置。通常用的比较多的是prxool。目前在j2ee中最通用的框架ssh中,hibernate的配置如下:

在spring
的applicationContext.xm.配置文件里配置数据源连接信息:

<!--
配置数据源 -->

<bean
id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">

<property
name="driverClassName">

<value>org.logicalcobwebs.proxool.ProxoolDriver</value>

</property>

<property
name="url">

<value>proxool.spring_user</value>

</property>

</bean>

在web.xml中做如下配置

<!--
制定proxool.xml放置的位置
-->

<param-value>WEB-INF/proxool.xml</param-value>

</context-param>

<listener>

将proxool.xml连接池配置文件放入到工程里WEB-INF目录下,其中proxool.xml的内容如下:

<?xml
version="1.0"
encoding="utf-8"?>

<!-- theproxool configuration can be embedded within your own application's.

Anything outside the "proxool" tagis ignored. -->

<something-else-entirely>

<proxool>

<alias>spring_user</alias>

<driver-url>jdbc:mysql://192.168.1.150:3306/chiyuweb</driver-url>

<driver-class>com.mysql.jdbc.Driver</driver-class>

<driver-properties>

<property
name="user"value="root"
/>

<property
name="password"value="123456"
/>

<property
name="useUnicode"value="true"
/>

<property
name="characterEncoding"value="GBK"
/>

</driver-properties>

<minimum-connection-count>5</minimum-connection-count>
<maximum-connection-count>50</maximum-connection-count>
<maximum-active-time>60000</maximum-active-time>

<house-keeping-test-sql>select
1</house-keeping-test-sql>

<prototype-count>5</prototype-count>

<house-keeping-sleep-time>60000</house-keeping-sleep-time>

</proxool>

</something-else-entirely>

注:在prxool这个文件里<alias>spring_user</alias>
表示连接的别名,一个连接池可以配置多个连接。

2 Hibernate 多条件分页查询

Hibernate的多条件查询的方法有很多种,比较常用的有两种,一种的创建Query对象,一种是创建Criteria对象。

Query对象查询:Hibernate上下文对象query= session.createQuery(HQL); query.setParameters(Object[]params,Type[]
types)返回一个根据参数查询的List集合。分页方法query.setFirstResult(START),START参数表示从查询到的结果集里第几条记录开始取query.setMaxResults(ROWS),ROWS表示分页信息中每页查询的记录条数。根据如上方法即可以实现hibernate多条件分页查询。其中query.setParameters方法的两个参数,params,types。他们是一一对应,成对出现的,所以最后用顺序表来保存他们的值,即两个用ArrayList来成对存储两个参数,然后将他们转化成数组。Type类型是org.hibernate中的Type类。如果参数是String类型,则参数需要设置成Hibernate.STRING,如他类型依次类推。时间类型需要注意如果比较精确到天,类型可设置成Hibernate.DATE,如果时间要精确到秒,则时间类型需要设置成Hibernate.TIMESTAMPS.

Criteria对象查询,调用session.createCriteria(Typetype).add() type是反射包里面的Type ,(若查User类 ,则传入User.class),add()方法能够传入字段的名称 addOrder方法能够传入排序规则,如此实现多条件查询。分页方法同query。
3Hibernate关联关系

Hibernate通常用的关联关系有三种:一对一,一对多和多对多。
一对一的方式有两种:一种是联合主键;一种是通过其他列来关联,即多对一的特殊形式,将多对一unique属性设置为true。配置方法网上都有这里就不啰嗦。
多对多关系并不提倡用many-to-many方式来配,通常用两个一对多的关系来实现。

一对多关系,这个关系的配的时候要特别注意,在多的一方<many-to-one/> 这边的lazy属性一般不要设置为false。这样配会大大的降低程序的性能。还有就是关联的列最好不要设置成外键关系,以为这样做加了外键会使数据库不易维护。关联列单独设置,在实体配置文件中这个列的约束这样设置 insert=”false” update=”false”
即可。

对于一对多自连接关系举一个实例来说明:
比如一个Person类里有老师和学生的关系
则Person.hbm.xml配置如下
<property name=”teacher_id” type=”java.lang.Integer” insert=”false” update=”false” />

<set
name="students"
cascade="save-update"
inverse="true"
lazy="true">

<key
column="teacher_id"
/>

<one-to-many
class="Person"
/>

</set>

<many-to-onename="student"
column="teacher_id"

class="Person"
cascade="save-update"/>

2.二级缓存

Hibernate对数据的缓存包括两个级:一级缓存,在Session的级别上进行,主要是对象缓存,以其id为键保存对象,在Session的生命期间存在;二级缓存,在SessionFactory的级别上进行,有对象缓存和查询缓存,查询缓存以查询条件为键保存查询结果,在SessionFactory的生命期间存在。默认地,Hibernate只启用一级缓存,通过正确地使用二级缓存,往往可以获得意想不到的性能。

1)对象缓存:

当抓取一个对象之后,Hiberate将其以id为键缓存起来,当下次碰到抓取id相同的对象时,可以使用如下配置

方法1:在缓存对象上配置

<class ...>

<cache useage="read-only/write/...." regions="group" />

</class>

useage表示使用什么类型的缓存,譬如只读缓存、读写缓存等等(具体参见Hibernate参考指南),值得注意的时,有部分缓存在Hibernate的实现中不支持读写缓存,譬如 JBossCache在Hibernate的实现中只是一种只读缓存,具体缓存实现对缓存类型的支持情况,可以参见org.hibernate.cache包

regions表示缓存分块,大部分的缓存实现往往对缓存进行分块,该部分是可选的,详细参见各缓存实现

方法2:在hibernate.cfg.xml中配置

<cache class=".." useage=".." regions=".."/>

我认为第二种更好,可以统一管理

2)查询缓存

查询时候将查询结果以查询条件为键保存起来,需要配置如下

A.在hibernate.cfg.xml中配置(启用查询缓存)

<property name="hibernate.cache.use_query_cache">true</property> (前面的属性名可参见常量

org.hibernate.cfg.Enviroment.USE_QUERY_CACHE)

B.程序

query.setCacheable(true);

query.setCacheRegions(...);

需要注意的是,查询缓存与对象缓存要结合更有效,因为查询缓存仅缓存查询结果列表的主键数据

一 般情况下在开发中,对一些比较稳定而又被频繁引用的数据,譬如数据字典之类的,将其进行二级缓存,对一些查询条件和查询数据变化不频繁而又常常被使用的查询,将其进行二级缓存。由于二级缓存是放在内存中,而且Hibernate的缓存不是弱引用缓存(WeekReference),所以注意不要将大块的数 据放入其中,否则可能会被内存造成比较大的压力。

3.批量数据操作

当进行大批量数据操作(几万甚至几十几百万)时,需要注意两点,一,批量提交,二,及时清除不需要的一级缓存数据

1) 所谓的批量提交,就是不要频繁使用session的flush,每一次进行flush,Hibernate将PO数据于数据库进行同步,对于海量级数据操 作来说是性能灾难(同时提交几千条数据和提交一条数据flush一次性能差别可能会是几十倍的差异)。一般将数据操作放在事务中,当事务提交时Hibernate自动帮你进行flush操作。

2)及时清除不需要的一级缓存数据:由于Hibernate默认采用一级缓存,而在session的生命期间,所有数据抓取之后会放入一级缓存中,而当数据规模比较庞大时,抓取到内存中的数据会让内存压力非常大,一般分批操作数据,被一次操作之后将一级缓存清除,譬如

session.clear(User.class)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: