Hibernate的事务管理
数据库事务
数据库的事务指的是把一系列的数据库操作组成一个单元,这个单元中的所有操作,这些操作要么全部完成,要么全部取消。
事务的特性(acid)
数据库事务必须具备ACID特性,ACID是Atomic(原子性)、Consistency(一致性)、Isolation(隔离性)和Durability(持久性)的英文缩写。
原子性:一个事务是有一个单元组成的,这个单元包含对数据库的若干个操作,而这些操作,要么全部成功,如果有一个失败,所有的操作全部取消,恢复到初始状态.
一致性:指数据库事务不能破坏关系数据的完成性以及业务逻辑上的一致性。例如对银行转帐事务,不管事务成功还是失败,应该保证事务结束后ACCOUNTS表中用户A和用户B的存款总额相等.
隔离性:指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间,不进行相互干扰。
持久性:指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。
编程式与声明式事务:
编程(Programmatical)式
声明式(Declarative)
事务的隔离级别
企业级的数据库每一秒钟都可能应付成千上万的并发访问,因而带来了并发控制的问题。由数据库理论可知,由于并发访问,在不可预料的时刻可能引发如下几个可以预料的问题:
脏读:包含未提交数据的读取。例如,事务1 更改了某行。事务2 在事务1 提交更改之前读取已更改的行。如果事务1 回滚更改,则事务2 便读取了逻辑上从未存在过的行。
不可重复读取:当某个事务不止一次读取同一行,并且一个单独的事务在两次(或多次)读取之间修改该行时,因为在同一个事务内的多次读取之间修改了该行,所以每次读取都生成不同值,从而引发不一致问题。
第二类丢失更新:是不可重复读的一种特例,如上,乙不做第二次查询而是直接操作完成,帐户内最终为100元,甲的操作被覆盖掉了,银行损失100元。感觉和第一类丢失更新类似。
幻象:通过一个任务,在以前由另一个尚未提交其事务的任务读取的行的范围中插入新行或删除现有行。带有未提交事务的任务由于该范围中行数的更改而无法重复其原始读取。
事务隔离级别:
Read Uncommitted:
- 更新丢失(false)
- 脏读(true)
- 不可重复读(true)
- 幻读(true)
Read Committed:
- 更新丢失(false)
- 脏读(false)
- 不可重复读(true)
- 幻读(true)
Repeatable Read:
- 更新丢失(false)
- 脏读(false)
- 不可重复读(false)
- 幻读(true)
Serializable:
- 更新丢失(false)
- 脏读(false)
- 不可重复读(false)
- 幻读(false)
Hibernate 中的事务
Hibernate中事务管理API
org.hibernate.Transaction
Commit()
Rollback()
锁:
ibernate当中,从宏观的角度设置数据库的不同的事务隔离级别来控制事务之间的并发执行。
微观角度,使用乐观锁或者悲观锁进一步对事务进行细化的并发控制
悲观锁
悲观锁(Pessimistic Locking),悲观的认为每次读取或者修改数据库时,其它的事务也在并发访问相同的数据
Transaction tx = session.beginTransaction();
Query query = session.createQuery("from Testbook tb");
query.setLockMode("tb",LockMode.UPGRADE);
List<Testbook> list=query.list();
tx.commit();
Session对象的lock()方法设置悲观锁
Transaction tx=session.beginTransaction();
Testbook tb=(Testbook)session.get(Tsetbook.class,new Integer(1));
session.lock(tb,LockMode.UPGRADE);
tx.commit();
或者
Transaction tx=session.beginTransaction();
Testbook tb=(Testbook)session.get(Tsetbook.class,new Integer(1),LockMode.UPGRADE);
tx.commit();
乐观锁
乐观锁,乐观的认为数据库中的数据很少发生同时被操作的问题。实现上,乐观锁可以通过数据的版本号(Version)比较机制实现
平衡应用系统的性能和数据一致性之间的矛盾,实际开发中,可以在数据库中设定隔离级别为ReadCommited,然后在程序中,在需要锁定的代码上面实现乐观锁定
版本号方式实现乐观锁:
public class Testbook implements java.io.Serializable{
//用来记录版本号,不需要提高getter与setter方法
private Interger version;
}
<class name="com.rbh.examples.Testbook" table="TESTBOOK"
optimistic-lock="version">
<id name="id" type="java.lang.Integer"></id>
<version name="version" column="version" access="field"/>
时间戳实现乐观锁:
public class Testbook implements java.io.Serializable{
private java.sql.Timestamp updateTime;
}
<class name="com.rbh.examples.Testbook" table="TESTBOOK"> <id name="id" type="java.lang.Integer"></id> <timestamp name="updateTime" column="update_time" access="field">
上一篇: 哲学家问题
下一篇: Hibernate的事务管理