hibernate 基于JDBC的事务管理

来源:互联网 发布:淘宝卖家如何屏蔽买家 编辑:程序博客网 时间:2024/05/16 06:52

 Hibernate是JDBC的轻量级封装,本身并不具备事务管理能力,在事务管理层,Hibernate将其委托给底层的JDBC或者JTA,以实现事务的管理和调度。

1.执行数据库事务 

每个数据库连接都有个全局变量@@autocommit,它有两个可选值: 

1:默认值,表示自动提交模式 每个SQL语句是一个独立的事务。

0:表示手工提交模式。在手工提交模式下,必须显式指定事务开始边界和结束边界:

–事务的开始边界:begin 

–提交事务:commit 

–撤销事务:rollback 

2.通过JDBC API声明事务边界的:

Connection提供了以下用于控制事务的方法: 

1.setAutoCommit(boolean autoCommit):设置是否自动提交事务 

2.commit():提交事务 

3.rollback():撤销事务 

下面具体的应用示例:

try {   con = java.sql.DriverManager.getConnection(dbUrl,dbUser,dbPwd);   //设置手工提交事务模式   con.setAutoCommit(false);   stmt = con.createStatement();   //数据库更新操作1   stmt.executeUpdate("update ACCOUNTS set BALANCE=900 where ID=1 ");   //数据库更新操作2   stmt.executeUpdate("update ACCOUNTS set BALANCE=1000 where ID=2 ");   con.commit(); //提交事务   }catch(Exception e) {   try{   con.rollback(); //操作不成功则撤销事务   }catch(Exception ex){   //处理异常   ……   }   //处理异常   ……   }finally{…}  

3.hibernate事务边界:
     在hibernate底层的事务管理就是利用的JDBC的事务管理。
1.声明事务的开始边界: 
Transaction tx=session.beginTransaction(); 
2.提交事务: tx.commit(); 
3.撤销事务: tx.rollback(); 
一个常见的hibernate操作如下

 private void savePerson(String name) {    Session session = HibernateUtil.getSessionFactory().getCurrentSession();    session.beginTransaction();    Customer customer = new Customer();    customer.setName(name);    session.save(customer);    session.getTransaction().commit();  }


四、使用Hibernate设置数据库隔离级别

在Hibernate的配置文件中可以显示的配置数据库事务隔离级别。每一个隔离级别用一个整数表示:

8 - Serializable 串行化
4 - Repeatable Read 可重复读
2 - Read Commited 可读已提交
1 - Read Uncommited 可读未提交

在hibernate.cfg.xml中使用hibernate.connection.isolation参数配置数据库事务隔离级别。

五、使用悲观锁解决事务并发问题

悲观锁的实现,往往依靠数据库提供的锁机制。

一个典型的依赖数据库的悲观锁调用:

select * from account where name=”Erica” for update

这条 sql 语句锁定了 account 表中所有符合检索条件( name=”Erica” )的记录。本次事务提交之前(事务提交时会释放事务过程中的锁),外界无法修改这些记录。

在Hibernate使用悲观锁十分容易,但实际应用中悲观锁是很少被使用的,因为它大大限制了并发性:

      

 六、使用乐观锁解决事务并发问题

 相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本(Version)记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个"version"字段来实现。
  乐观锁的工作原理:读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。

Hibernate为乐观锁提供了3中实现:

1. 基于version

2. 基于timestamp

3. 为遗留项目添加添加乐观锁 

配置基于version的乐观锁:

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping>    <class name="com.suxiaolei.hibernate.pojos.People" table="people">        <id name="id" type="string">            <column name="id"></column>            <generator class="uuid"></generator>        </id>                <!-- version标签用于指定表示版本号的字段信息 -->        <version name="version" column="version" type="integer"></version>        <property name="name" column="name" type="string"></property>            </class></hibernate-mapping>

配置基于timestamp的乐观锁:

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping>    <class name="com.suxiaolei.hibernate.pojos.People" table="people">        <id name="id" type="string">            <column name="id"></column>            <generator class="uuid"></generator>        </id>                <!-- timestamp标签用于指定表示版本号的字段信息 -->        <timestamp name="updateDate" column="updateDate"></timestamp>        <property name="name" column="name" type="string"></property>            </class></hibernate-mapping>

遗留项目,由于各种原因无法为原有的数据库添加"version"或"timestamp"字段,这时不可以使用上面两种方式配置乐观锁,Hibernate为这种情况提供了一个"optimisitic-lock"属性,它位于<class>标签上:

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping>    <class name="com.suxiaolei.hibernate.pojos.People" table="people" optimistic-lock="all">        <id name="id" type="string">            <column name="id"></column>            <generator class="uuid"></generator>        </id>        <property name="name" column="name" type="string"></property>    </class></hibernate-mapping>

将该属性的值设置为all,让该记录所有的字段都为版本控制信息。