您的位置:首页 > 其它

Hibernate——处理并发

2013-11-20 21:21 155 查看
并发问题可以归类为以下几类:

第一类丢失更新:撤销一个事务时,把其他事务已提交的更新数据覆盖。
脏读:一个事务读取到另一个事务未提交的更新。
虚读:一个事务读取到另一个事务已提交的新插入数据。
不可重复读:一个事务读取到另一个事务已提交的事务。
第二类丢失更新:一个事务覆盖另一个事务已提交的更新数据。

数据库系统的锁:

根据锁的粒度分为:

数据库级锁:锁定数据库
表级锁:锁定一个表
区域级锁:锁定数据库的特定区域
页面级锁:锁定数据库的特定页面
键值级锁:锁定数据库中带有索引的一行数据
行级锁:锁定一行数据
按照封锁程度可以分为:

 1、共享锁

共享锁用于读操作,它是非独占的,允许其它事务读取其锁定的资源,但不允许其它资源更新锁定的资源。

加锁条件:当一个事务执行select语句时,数据库系统就会自动为这个事务添加一个共享锁,来锁定被查询的数据。

解锁条件:当数据被读取后,数据库系统就自动解锁,例如当执行"select * from user"时,数据库系统首先锁定第一行,然后读取,然后解锁第一行,对第二行加锁,允许其它事务更新没锁定的行。

2、独占锁:使用于修改数据的场合,它锁定的数据其它事务既不能读取也不能更新。

加锁条件:当执行select、update等sql语句时,数据库系统自动对所包括的数据资源加锁。

解锁条件:一直到事务执行完毕才解锁。

3、更新锁:

加锁条件:当执行update语句时,系统为事务加上更新锁。

解锁条件:当读取完数据要对数据进行修改时,更新锁会升级为独占锁。

数据库的数据隔离级别:

1、Serializable(串行化):当数据库系统使用Serializable隔离级别时,一个事务在执行过程中完全看不到其它事务对数据库所做的操作。当两个事务操作数据库中相同的数据

的时候,如果第一个事务已经在访问数据,则第二个事务必须停下来等待第一个事务结束。

2、Repeatable Read(可重复度):一个事务在执行过程中可以看到其它事务已提交的新插入的数据,但是不能看到其它事务已提交的更新数据。

3、Read Commited(读已提交数据):一个事务在执行过程中可以看到其它事务已提交的新插入的数据,而且可以看到其它事务已提交的更新数据。

4、Read Umcommited(读未提交数据):一个事务在执行过程中可以看到其它事务未提交的新插入的数据,而且可以看到其它事务未提交的更新数据。

在应用程序中设置隔离级别:

JDBC数据库连接使用数据库默认的隔离级别。可以在hibernate中显示的设置隔离级别,每个级别对应一个整数,从上到下依次为1、2、4、8

eg:hibernate.connection.isolation=1

对于从数据库连接池中获取的每一个连接,hibernate都会把它改为使用Read Commiter隔离级别。在受管理环境中,如果hibernate使用的数据库连接来自应用服务器提供的

数据源,hibernate不会修改这些连接的隔离级别,应该在应用服务器中修改隔离级别。

从应用程序的角度,锁可以分为:

1、悲观锁:指在应用程序中显示的为数据资源加锁。悲观锁假定当前事务操作资源时,必定有其它事务同时访问该资源。为了避免当前事务操作受到影响,先给资源加锁。

2、乐观锁:乐观锁假定当前事务操作资源时,肯定不会有其它资源同时访问该资源。因此完全依靠数据库系统的隔离级别来管理锁。应用程序使用版本控制来避免并发问题。

Oracle、MySql都支持”select ... for update“形式的语句,这种语句显示指定使用独占锁来锁定资源。

在hibernate中使用get()和load()加载数据时,可以用以下形式声明悲观锁

session.get(object.class,id,LockMode.UPGRADE)

org.hibernate.LockMode表示锁定模式。

锁定模式描述
LockMode.NONE如果在hibernate中存在Account对象,就直接返回该对象的引用,否则就通过

select语句到数据库中获取。这是默认值。
LockMode.READ不管hibernate中是否存在Account对象,总是执行select语句到数据库中查找,

如果映射文件中配置了版本控制,就执行版本检查,比较缓存中的Account对象

是否和数据库中的Account版本一致。
LockMode.UPGRADE不管hibernate中是否存在Account对象,总是执行select语句到数据库中查找,

如果映射文件中配置了版本控制,就执行版本检查,比较缓存中的Account对象

是否和数据库中的Account版本一致。如果数据库支持悲观锁,就执行select...for update

语句,否则执行普通的select语句。
LockMode.UPGRADE_NOWAIT和上一个有一样的功能。同时,对于oracle等支持”update nowait“的数据库,

执行”select ..for update“
LockMode.FORCE强制更新数据库对象的版本属性,表明这个属性被更新了。
利用hibernate的版本控制来实现乐观锁

<verson>和<timestamp>都可以实现版本控制,不过一般使用verson,因为各地时间可能不统一》。。

利用verson实现版本控制,首先在类中添加verson属性,然后再配置文件的<id>元素后紧接着配置<verson>元素...

verson属性不用手动给它赋值。

只有当hibernate通过update语句更新一个对象时,才会更新它的verson属性。版本控制不具有级联特性,但可以通过强制版本更新来修改关联对象的版本属性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hibernate