Hibernate事物隔离级别[转]

事务不完全隔离会导致:脏读,不可重复读,幻读, 针对由事务的不完全隔离所引起的上述问题,提出了一些隔离级别,用来防范这些问题。
读操作未提交(Read Uncommitted): 说明一个事务在提交前,其变化对于其他事务来说是可见的。这样脏读、不可重读和幻读都是允许的。当一个事务已经写入一行数据但未提交,其他事务都不能再写入此行数据;但是,任何事务都可以读任何数据。这个隔离级别使用排写锁实现。
读操作已提交(Read Committed): 读取未提交的数据是不允许的,它使用临时的共读锁和排写锁实现。这种隔离级别不允许脏读,但不可重读和幻读是允许的。
可重读(Repeatable Read): 说明事务保证能够再次读取相同的数据而不会失败。此隔离级别不允许脏读和不可重读,但幻读会出现。 可串行化(Serializable): 提供最严格的事务隔离。这个隔离级别不允许事务并行执行,只允许串行执行。这样,脏读、不可重读或幻读都可发生。 事务隔离与隔离级别的关系如表9-2所示。 表9-2  事务隔离与隔离级别的关系

隔离级别 脏读(Dirty Read) 不可重复读(Unrepeatable Read) 幻读(Phantom Read) 读操作未提交 (Read Uncommitted) 可能 可能 可能      
读操作已提交 (Read Committed) 不可能 可能 可能      
可重读 (Repeatable Read) 不可能 不可能 可能
可串行化 (Serializable) 不可能 不可能 不可能      

在一个实际应用中,开发者经常不能确定使用什么样的隔离级别。太严厉的级别将降低并发事务的性能,但是不足够的隔离级别又会产生一些小的Bug ,而这些Bug 只会在系统重负荷(也就是并发严重时)的情况下才会出现。   
一般来说,读操作未提交(Read Uncommitted)是很危险的。一个事务的回滚或失败都会影响到另一个并行的事务,或者说在内存中留下和数据库中不一致的数据。这些数据可能会被另一个事务读取并提交到数据库中。这是完全不允许的。   
另外,大部分程序并不需要可串行化隔离(Serializable Isolation)。虽然,它不允许幻读,但一般来说,幻读并不是一个大问题。可串行化隔离需要很大的系统开支,很少有人在实际开发中使用这种事务隔离模式。 现在留下来的可选的隔离级别是读操作已提交(Read Committed)和可重读(Repeatable Read)。

Hibernate 可以很好地支持可重读(Repeatable Read)隔离级别。 在Hibernate配置文件中设置隔离级别 JDBC连接数据库使用的是默认隔离级别,即读操作已提交(Read Committed)和可重读(Repeatable Read)。
在Hibernate的配置文件hibernate.properties中,可以修改隔离级别: #hibernate.connection.isolation 4
在上一行代码中,Hibernate事务的隔离级别是4,这是什么意思呢?级别的数字意义如下。 1:读操作未提交(Read Uncommitted)
2:读操作已提交(Read Committed)
4:可重读(Repeatable Read)
8:可串行化(Serializable)

因此,数字4表示“可重读”隔离级别。如果要使以上语句有效,应把此语句行前的注释符“#”去掉: hibernate.connection.isolation 4 也可以在配置文件hibernate.cfg.xml 中加入以下代码:  
<session-factory> ….. // 把隔离级别设置为4
<property name=” hibernate.connection.isolation”>4</property> …… </session-factory>

在开始一个事务之前,Hibernate 从配置文件中获得隔离级别的值。
在Hibernate中使用JDBC事务 Hibernate对JDBC进行了轻量级的封装,它本身在设计时并不具备事务处理功能。Hibernate将底层的JDBCTransaction或JTATransaction进行了封装,再在外面套上Transaction和Session的外壳,其实是通过委托底层的JDBC或JTA来实现事务的处理功能的。 要在Hibernate中使用事务,可以在它的配置文件中指定使用JDBCTransaction或者JTATransaction 。
在hibernate.properties中,查找“transaction.factory_class”关键字,得到以下配置:
# hibernate.transaction.factory_class  org.hibernate.transaction.JTATransactionFactory # hibernate.transaction.factory_class  org.hibernate.transaction.JDBCTransactionFactory Hibernate的事务工厂类可以设置成JDBCTransactionFactory或者JTATransactionFactory。如果不进行配置,Hibernate就会认为系统使用的事务是JDBC事务。

在JDBC的提交模式(commit mode)中,如果数据库连接是自动提交模式(auto commit mode),那么在每一条SQL语句执行后事务都将被提交,提交后如果还有任务,那么一个新的事务又开始了。 Hibernate在Session控制下,在取得数据库连接后,就立刻取消自动提交模式,即Hibernate在一个执行Session 的beginTransaction()方法后,就自动调用JDBC层的setAutoCommit(false)。如果想自己提供数据库连接并使用自己的SQL语句,为了实现事务,那么一开始就要把自动提交关掉(setAutoCommit(false)),并在事务结束时提交事务。 使用JDBC事务是进行事务管理最简单的实现方式,Hibernate对于JDBC事务的封装也很简单。
下面是一个在Hibernate中使用JDBC事务的例子:
try { 
Session session = HibernateUtil.currentSession(); 
Transaction tx = session.beginTransaction();  // 在默认情况下,开启一个JDBC 事物 
for(int i=0; i<10; i++)  { 
Student stu = new Student(); stu.setName("Student" + i); session.save(stu); 
} 
tx.commit(); // 提交事务 
session.close(); 
} catch(Exception e) {… tx.rollback();   // 事务回滚 } 


在Hibernate中使用JTA事务 JTA(Java Transaction API)是事务服务的J2EE解决方案。本质上,它是描述事务接口的J2EE模型的一部分,开发人员直接使用该接口或者通过J2EE容器使用该接口来确保业务逻辑能够可靠地运行。
JTA有3个接口,它们分别是UserTransaction接口、TransactionManager接口和Transaction接口。这些接口共享公共的事物操作,例如commit()和rollback(),但也包含特殊的事务操作,例如suspend()、resume()和enlist(),它们只出现在特定的接口上,以便在实现中允许一定程度的访问控制。 在一个具有多个数据库的系统中,可能一个程序会调用几个数据库中的数据,需要一种分布式事务,或者准备用JTA来管理跨Session的长事务,那么就需要使用JTA事务。下面介绍如何在Hibernate的配置文件中配置JTA 事务。在hibernate.properties文件中设置如下(把JTATransactionFactory所在的配置行的注释符“#”取消掉): hibernate.transaction.factory_class  org.hibernate.transaction.JTATransactionFactory # hibernate.transaction.factory_class  org.hibernate.transaction.JDBCTransactionFactory 或者在hibernate.cfg.xml 文件中配置如下:
<session-factory>

<property name=” hibernate.transaction.factory_class”> org.hibernate.transaction.JTATransactionFactory </property>
……
</session-factory>

下面是一个应用JTA 事务的例子:
javax.transaction.UserTransaction tx = null; 
tx = new initialContext().lookup(” javax.transaction.UserTransaction ”) ; 
tx.begin(); 
Session s1 = sf.openSession(); 
…… 
s1.flush();  
s1.close(); 
Session s2 = sf.openSession(); 
…… 
s2.flush();  
s2.close(); 
tx.commit();

你可能感兴趣的:(Hibernate)