首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

Hibernate中的事宜和并发控制

2012-09-01 
Hibernate中的事务和并发控制1.事务介绍:1.1.事务的定义:事务就是指作为单个逻辑工作单元执行的一组数据操

Hibernate中的事务和并发控制
1.    事务介绍:
1.1.       事务的定义:
事务就是指作为单个逻辑工作单元执行的一组数据操作,这些操作要么必须全部成功,要么必须全部失败,以保证数据的一致性和完整性。
1.2.       事务具有ACID属性:
o 原子性(Atomic):事务由一个或多个行为绑在一起组成,好像是一个单独的工作单元。原子性确保在事务中的所有操作要么都发生,要么都不发生。
o 一致性(Consistent):一旦一个事务结束了(不管成功与否),系统所处的状态和它的业务规则是一致的。即数据应当不会被破坏。
o 隔离性(Isolated):事务应该允许多个用户操作同一个数据,一个用户的操作不会和其他用户的操作相混淆。
o 持久性(Durable):一旦事务完成,事务的结果应该持久化。



     事务的ACID特性是由关系数据库管理系统(RDBMS)来实现的。
o 数据库管理系统采用日志来保证事务的原子性、一致性和持久性。日志记录了事务对数据库所做的更新,如果某个事务在执行过程中发生错误,就可以根据日志,撤销事务对数据库已做的更新,使数据库退回到执行事务前的初始状态。
o 数据库管理系统采用锁机制来实现事务的隔离性。当多个事务同时更新数据库相同的数据时,只允许持有锁的事务能更新该数据,其他事务必须等待,直到前一个事务释放了锁,其他事务才有机会更新该数据。
2.    数据库事务声明:
数据库系统的客户程序只要向数据库系统声明了一个事务,数据库系统就会自动保证事务的ACID特性。在JDBC API中,java.sql.Connection类代表一个数据库连接。它提供了以下方法控制事务:
1.         setAutoCommit(Boolean autoCommit):设置是否自动提交事务。
2.         commit():提交事务。
3.         rollback():撤销事务。
2.1.       JDBC API声明事务的示例代码如下:


Connection = null;
PreparedStatement pstmt = null;
try{
con = DriverManager.getConnection(dbUrl, username, password);
//设置手工提交事务模式
con.setAutoCommit(false);
pstmt = ……;
pstmt.executeUpdate();
//提交事务
con.commit();
}catch(Exception e){
//事务回滚
con.rollback();
…..
} finally{
    …….
}


Hibernate对JDBC进行了轻量级的对象封装,Hibernate本身在设计时并不具备事务处理功能,平时所用的Hibernate的事务,只是将底层的JDBCTransaction或者JTATransaction进行了一下封装,在外面套上Transaction和Session的外壳,其实底层都是通过委托底层的JDBC或JTA来实现事务的调度功能。

2.2.       Hibernate中使用JDBC事务:
要在Hibernate中使用事务,可以配置Hibernate事务为JDBCTransaction或者JTATransaction,这两种事务的生命周期不一样,可以在hibernate.cfg.xml中指定使用的是哪一种事务。以下配置为使用JDBC事务。注:如果不进行配置,Hibernate也会默认使用JDBC事务。

package org.qiujy.domain.versionchecking; import java.util.Date; import org.hibernate.HibernateException;import org.hibernate.Session;import org.hibernate.Transaction;import org.qiujy.common.HibernateSessionFactory; public class TestVersionChecking {             public static void main(String[] args) {              Product prod = new Product();              prod.setName("IBM thinkPad T60");              prod.setUnitCost(new Double(26000.00));              prod.setDescription("笔记本电脑");              prod.setPubTime(new Date());                           //test start.......              Session session = HibernateSessionFactory.getSession();              Transaction tx =null;              try{                     tx = session.beginTransaction();                                         session.save(prod);                                    tx.commit();              }catch(HibernateException e){                     if(tx != null){                            tx.rollback();                     }                     e.printStackTrace();              }finally{                     HibernateSessionFactory.closeSession();              }       //进行更新 测试..              prod.setDescription("新款的");                           Session session2 = HibernateSessionFactory.getSession();              Transaction tx2 =null;              try{                     tx2 = session2.beginTransaction();                                         session2.update(prod);                                   tx2.commit();              }catch(HibernateException e){                     if(tx2 != null){                            tx2.rollback();                     }                     e.printStackTrace();              }finally{                     HibernateSessionFactory.closeSession();              }       }}


新增数据时产生的SQL是:
insert into products (version, name, description, unitCost, pubTime)
    values(?, ?, ?, ?, ?)

程序无需为Product对象的version属性显示赋值,当持久化一个Product对象时,Hibernate会自动为它赋初始值为0。
更新数据时产生的SQL是:
    update
        products
    set
        version=?,
        name=?,
        description=?,
        unitCost=?,
        pubTime=?
    where
        id=?
        and version=?

当Hibernate更新一个Product对象,会根据它的id和version属性到相应的数据库表中定位匹配的记录,如果存在这条匹配的记录,就更新记录,并且把version字段的值加1。若找不到匹配的记录,此时Hibernate会抛出StaleObjectStateException。

需要注意的是,由于乐观锁定是使用系统中的程序来控制,而不是使用数据库中的锁定机制,因而如果有人故意自行更新版本信息来超过检查,则锁定机制就无效。所以建议把持久化类中的version的get方法设置为private的。
5.1.2.       使用时间戳(<timestamp>):
跟版本检查的用法相似。不再多说。
5.2.       悲观锁(Pessimistic Locking):
悲观锁假定当前事务操纵数据资源时,肯定还会有其他事务同时访问该数据资源,为了避免当前事务的操作受到干扰,先锁定资源。尽管悲观锁能够防止丢失更新和不可重复读这类并发问题,但是它影响并发性能,因此应该很谨慎地使用悲观锁。


Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1874599

热点排行