RSS

Hibernate的事务管理

08 Apr

事务  编程式与声明式事务

编程式(Programmatical)

声明式(Declarative) – 修改配置文件来进行事务的控制

 

事务隔离级别

隔离级别

更新丢失

脏读

不可重复读

幻读

Read Uncommitted

×

Read Commited

×

×

Repeatable Read

×

×

×

Serializable

×

×

×

×

 

Hibernate中的事务

<hibernate-configuration>

<session-factory>

<property name="hibernate.transaction.factory_class">

org.hibernate.transaction.JTATransactionFactory

</property>

</session-factory>

</hibernate-configuration>
特别指定JTA方式管理底层数据库事务,默认是JDBC管理的

Hiberante中事务管理API

org.hibernate.Transaction

Commit();

Rollback();

底层使用JDBC或者JTA来对底层数据库事务进行管理

Transaction tx = session.beginTransaction();

try{

session.save(gb);

}catch(Exception e){

e.printStackTrace();

if(tx.isActive()){

tx.rollback();

}

}

tx.commit();

Hibernate当中,从宏观的角度设置数据库不同事务隔离级别来控制事务之间的并发执行。

微观角度,使用乐观锁或者悲观锁进一步对事务进行细化的并发控制

 

悲观锁

悲观锁(Pessimistic Locking)悲观的人为每次读取或者修改数据库时,其他的事务也在并发访问相同的数据。当查询时,其他事务都不可以处理这个数据,当这个事务提交后,其他事务才可以操作这个数据

Transaction tx = session.beginTransaction();

Query query = session.createQuery("from GuestBook gb");

query.setLockMode("gb", LockMode.UPGRADE);

List<GuestBook> list = query.list();

tx.commit();
Session对象的lock()方法设置悲观锁
Transaction tx = session.beginTransaction();
GuestBook gb = (GuestBook) session.get(GuestBook.
class, new Integer(1));
session.lock(gb, LockMode.UPGRADE);
tx.commit();
或者
Transaction tx = session.beginTransaction();
GuestBook gb = (GuestBook) session.get(GuestBook.class, new Integer(1), LockMode.UPGRADE);
tx.commit();
 

乐观锁

1. 乐观锁,乐观的认为数据库中的数据很少发生同时被操作的问题。实际上,乐观锁可以通过数据的版本号(version)比较机制实现。

2. 平衡应用系统的性能和数据一致性之间的矛盾,实际开发中,可以在数据库中设定隔离级别为Read Commited,然后在程序中,在需要锁定的代码上面实现乐观锁定。

———————————————–

版本号方式实现乐观锁(需要在数据库中加入一列不为空的version列, Hibernate会自动操作它,不要人为操作)

public class GuestBook implements java.io.Serializable{

//用来记录版本号,不需要提供getter与setter方法

private Integer version;

}

<class name="hibernate.example.vo.GuestBook" table="GUESTBOOK" optimistic-lock="version">

<id name="id" type="java.lang.Integer"/>

<version name="version" column="version" access="field"/>

数据库操作代码没有任何变化       

Transaction tx = session.beginTransaction();

GuestBook gb = (GuestBook) session.get(GuestBook.class);

tx.commit();

测试代码

Session session1 = HibernateSessionFacotryUtil.getSessionFactory().openSession();

Session session2 = HibernateSessionFacotryUtil.getSessionFactory().openSession();

Transaction tx1 = session1.beginTransaction();

Transaction tx2 = session2.beginTransaction();

GuestBook gb1 = (GuestBook) session.get(GuestBook.class, 101);

GuestBook gb2 = (GuestBook) session.get(GuestBook.class, 101);

gb1.setTitle("update title");

gb2.setContent("update content");

tx1.commit();

tx2.commit();

session1.close();

session2.close();
当提交第二个会报错,只有第一个成功。开始的时候,他们读取的都是同一个version,第一个提交后版本号会增加1,但是第二个提交的时候发现version版本号不对,所以会报错。
———————————————–
时间戳实现乐观锁(增加一个时间戳字段类型为TIMESTAMP(6))

public class GuestBook implements java.io.Serializable{

private java.sql.Timestamp updateTime;//不需要提供getter/setter方法

}

<class name="hibernate.example.vo.GuestBook" table="GUESTBOOK">

<id name="id" type="java.lang.Integer"/>

<timestamp name="updateTime" column="update_time" access="field"/>

测试代码

Session session1 = HibernateSessionFacotryUtil.getSessionFactory().openSession();

Session session2 = HibernateSessionFacotryUtil.getSessionFactory().openSession();

Transaction tx1 = session1.beginTransaction();

Transaction tx2 = session2.beginTransaction();

GuestBook gb1 = (GuestBook) session.get(GuestBook.class, 101);

GuestBook gb2 = (GuestBook) session.get(GuestBook.class, 101);

gb1.setTitle("update title");

gb2.setContent("update content");

tx1.commit();

tx2.commit();

session1.close();

session2.close();

当提交第二个会报错,只有第一个成功。比较timestamp的值,由于第一个提交了,所以导致第二个和第一个不同步,导致无法提交第二个。

Advertisements
 
Leave a comment

Posted by on 04/08/2011 in HIBERNATE

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

 
%d bloggers like this: