Hibernate如何提升数据库查询的性能(五)

2014-11-24 09:17:19 · 作者: · 浏览: 2
之前通过Query对象的setLockMode()方法设置了访问User对象的模式,这样,这个程序在执行的时候就会使用以下的SQL语句:

select user0_.userId as userId0_, user0_.name as name0_, user0_.age as age0_

from USERINFO user0_ for update

除了Query对象外,也可以在使用Session的load()或是lock()时指定锁模式。

除了前面所提及的两种锁模式外,还有三种Hibernate内部自动对数据进行加锁的模式,但它的处理是与数据库无关的。

LockMode.WRITE:在insert或update时进行锁定,Hibernate会在调用save()方法时自动获得锁。

LockMode.READ:在读取记录时Hibernate会自动获得锁。

LockMode.NONE:没有锁。

如果数据库不支持所指定的锁模式,Hibernate会选择一个合适的锁替换,而不是抛出一个异常。

乐观锁

乐观锁(Optimistic Locking)认为资料的存取很少发生同时存取的问题,因而不做数据库层次上的锁定。为了维护正确的数据,乐观锁是使用应用程序上的逻辑来实现版本控制的。

在使用乐观锁策略的情况下,数据不一致的情况一旦发生,有几个解决方法,一种是先更新为主,一种是后更新为主,比较复杂的就是检查发生变动的数据来实现,或是检查所有属性来实现乐观锁。

Hibernate中通过检查版本号来判断数据是否已经被其他人所改动,这也是Hibernate所推荐的方式。在数据库中加入一个version字段记录,在读取数据时连同版本号一同读取,并在更新数据时比较版本号与数据库中的版本号,如果等于数据库中的版本号则予以更新,并递增版本号,如果小于数据库中的版本号就抛出异常。

下面就来在前面例子的基础上进行Hibernate乐观锁的测试。

首先需要修改前面所实现的业务对象,在其中增加一个version属性,用来记录该对象所包含数据的版本信息,修改后的User对象如清单14.5所示。

清单14.5 修改后的User对象

package cn.hxex.hibernate.lock;

public class User {

private String id;

private Integer version; // 增加版本属性

private String name;

private Integer age;

// 省略了getter和setter方法

……

}

然后是修改映射文件,增加version属性的配置。在这里需要注意的是,这里的version属性应该使用专门的元素来进行配置,这样才能使其发挥乐观锁的作用。如果还使用元素来进行配置,那么Hibernate只会将其作为一个普通的属性来进行处理。

修改后的映射文件如清单14.6所示。

清单14.6 修改后的映射文件

< xml version="1.0" >

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

接下来还要进行测试主程序的修改。由于需要模拟两个人同时修改同一个记录的情况,所以在这里需要将主程序修改为是可以多线程执行的,然后在run()方法中,调用对User对象的修改程序。

实现后的主测试程序如清单14.7所示。

清单14.7 修改后的测试主程序

package cn.hxex.hibernate.lock;

import java.net.URL;

import java.util.List;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.hibernate.LockMode;

import org.hibernate.Query;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.Transaction;

import org.hibernate.cfg.Configuration;

public class LockMain extends Thread{

……

public void testOptimisticLock() {

SessionFactory sf = LockMain.getSessionFactory();

Session session = sf.openSession();

Transaction tx = session.beginTransaction();

User userV1 = (User)session.load( User.class, "1" );

// 等第二个进程执行

try {

sleep( 3000 );

} catch (InterruptedException e) {

e.printStackTrace();

}

userV1.setAge(new Integer(32));

tx.commit();

session.close();

}

public void run() {

testOptimisticLock();

}

public static void main(String[] args) {

// LockMain main = new LockMain();

// main.testPessimisticLock();

LockMain main1 = new LockMain();

main1.start();

LockMain main2 = new