首页 > 代码库 > hibernate的事务管理

hibernate的事务管理

一、数据库事务

1. 概念:

数据库事务指把一系列数据库操作组成一个单元,要么全部取消,要么全部完成。即提交和回滚操作。

2. 特性:

(1)  原子性

   表示组成一个事务的多个数据库操作是一个不可分隔的原子单元,只有所有的操作执行成功,整个事务才提交,事务中任何一个数据库操作失败,已经执行的任何操作都必须撤销,让数据库返回到初始状态;

(2) 一致性

   事务执行前后必须在逻辑上一致,即数据不会被破坏。如从A账户转账100元到B账户,不管操作成功与否,AB的存款总额是不变的;

(3) 隔离性

    在并发数据操作时,不同的事务拥有各自数据空间,彼此之间相互隔离,隔离级别可以设置。

(4)  持久性

    对数据库的修改都要写入硬盘中,若在操作过程中发生断电或系统错误,数据库要保证未提交的事务在下次启动之前要撤销,结束的事务要把修改结果写入硬盘。

3. 事务的使用分类

(1) 编程式事务

    直接使用JDBCJTA或者相关框架的API以编写代码的方式设置事务的边界和隔离级别。(JDBC中的事务是自动提交的,可以通过Connection对象的setAutoCommit(false)方法取消自动提交。

(2)   声明式事务

    依赖应用服务器提供的服务(weblogic server)或者相关框架的APIspring framework)在配置文件中设置相关信息。

4. 并发访问数据库可能引发的问题

(1)  脏读

    A事务读取B事务尚未提交的更改数据,并在这个数据的基础上操作。即恰巧读取了B事务回滚之前的数据。

(2) 不可重复读

    A事务读取了B事务已经提交的更改数据(更新和删除),导致数据处理上的混乱。即A事务两次读取期间,B事务进行了更新或删除操作。

为防止,只需要对操作的数据添加行级锁,阻止操作中的数据发生变化。

(3) 幻读

    A事务读取B事务提交的新增数据(插入),这时A事务将出现幻象读的问题。幻象读一般发生在计算统计数据的事务中。

为防止,需要添加表级锁,将整个表锁定,防止新增数据。

(4)第一类丢失更新

    A事务撤销时,把已经提交的B事务的更新数据覆盖了。若数据库没有隔离事务就会发生该现象。

(5) 第二类丢失更新

    A事务提交时,覆盖了B事务已经提交的数据,造成B事务所做操作丢失。

5. 事务隔离级别:

隔离性是通过数据库的表或字段加锁实现的。事务隔离级别分为以下四种:

(1) Read Uncommitted 读未提交

    一个事务可以读取另一个事务已更新但未提交的数据,但另一事务提交前不允许写入。

(2) Read committed 读提交(oracle默认事务)

    一个事务仅可以读取另一个事务已提交的更新数据。

(3) Repeatable read 重复读

    一个事务已读取的数据不允许其他事务的写入。

(4)Serializable 序列化

    所以事务序列化进行,不能并发执行。

   √: 可能出现    ×: 不会出现

隔离级别

更新丢失

脏读

不可重复读

幻读

Read uncommitted

×

Read committed

×

×

Repeatable read

×

×

×

Serializable

×

×

×

×

 

二、hibernate中的事务

hibernate是对JDBC的封装,本身并不具备事务处理能力,他将事务处理交给底层的JDBC或者JTA处理。

1. 锁

    在hibernate中不仅可以通过宏观角度设置数据库的不同事务隔离级别,还可以从微观角度使用乐观锁和悲观锁进一步控制并发事务。(例如在结算时不允许数据发生变化可以对该数据加锁)

2. Hibernate的锁定模式

    Hibernate可以自动设置锁定模式,还可以调用Session对象的load()lock()方法,QueryCriteria对象的setLockMode()方法显式设置并使用下述模式。

1LockMode.NONE

    如果在Hibernate的缓存中存在指定对象,就直接返回该对象的引用;否则就通过Select语句到数据库中加载该对象。这是默认值

2LockMode.Read

    不管Hibernate的缓存中是否存在指定对象,总是通过select语句到数据库中加载该对象。

3LockMode.UPGRADE

    不管Hibernate的缓存中是否存在指定对象,总是通过select语句到数据库中加载该对象;如果数据库系统支持悲观锁就执行select ... for update语句,如果数据库系统不支持悲观锁,就执行普通的select语句。

4LockMode.UPGRADE_NOWAIT

    和LockMode.UPGRADE具有同样的功能。此外对于Oracle数据库,执行select ... for update nowait语句

5LockMode.WRITE

    当Hibernate向数据库插入或者更新一个对象时,会自动使用此模式。Hibernate会在写入数据时自动使用该模式。

3.  悲观锁

     悲观的认为每次读取或者修改数据库数据时,其他事务也在访问。所以悲观锁会对读取的数据进行锁定,其他事务不能访问。

使用方法:

   QuerysetLockMode()方法:query.setLockMode(“book”,LockMode.UPGRADE);

   Sessionlock()方法:     session.lock(book, LockMode.UPGRADE);

4. 乐观锁

1乐观锁定采用的版本策略有:先提交为主(First commit win)、后提交为主(Last commit win)、合并冲突更新(Merge cofilcting updates)

2Hibernate推荐采用“版本号来实现先提交为主”的乐观锁定模式。在数据库中增加一列version,每次读取时,连该列一起读取,在更新的时候将此版本号和数据库中的版本号进行比较,如果大于等于则可以更新,如果小于则抛出异常。其是在配置文件中设置的。

3也可以采用时间戳实现乐观锁,比较时间戳大小。


注:本文参考《Hibernate开发与实战》 刘伟 张利国 电子工业出版社 一书

本文出自 “java我的最爱” 博客,请务必保留此出处http://lindianli.blog.51cto.com/7129432/1433111