SSH:Hibernate框架(Hibernate数据库事务与隔离级别)

  数据库事务:事务是指一组相互依赖的操作行为,如银行交易、股票交易或网上购物。事务的成功取决于这些相互依赖的操作行为是否都能执行成功,只要有一个操作行为失败,就意味着整个事务失败。关于事务的一个经典例子就是:A到银行办理转账事务,把100元钱转到B的账号上,这个事务包含以下操作行为: 

(1)从A的账户上减去100元。 

(2)往B的账户上增加100元。

      显然,以上两个操作必须作为一个不可分割的工作单元。假如仅仅第一步操作执行成功,使得Tom的账户上扣除了100元,但是第二步操作执行失败,Jack的账户上没有增加100元,那么整个事务失败。 数据库事务是对现实生活中事务的模拟,它由一组在业务逻辑上相互依赖的SQL语句组成。 

 下面我们一起来看一下数据库事务的生命周期:

                                             

这个数据库事务的生命周期图反应出数据库事务的三个边界:

1.事务的开始边界。 

2.事务的正常结束边界(COMMIT):提交事务,永久保存被事务更新后的数据库状态。 

3.事务的异常结束边界(ROLLBACK):撤销事务,使数据库退回到执行事务前的初始状态。 

其实每个数据库连接都有个全局变量@@autocommit,表示当前的事务模式,它有两个可选值: 0:表示手工提交模式。 1:默认值,表示自动提交模式 

在自动提交模式下,每个SQL语句都是一个独立的事务。也就是说,每执行一条sql语句,数据库都会自动提交这个事务,当我们用数据库另一个客户端去查询的时候,我们可以看到这个新修改或插入的数据。在手工提交模式下,必须显式指定事务开始边界和结束边界: 

–事务的开始边界:begin 

–提交事务:commit 

–撤销事务:rollback 

下面我们来看一下通过JDBC API是如何声明事务边界的:

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

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

2.commit():提交事务 

3.rollback():撤销事务 

下面我们看一下具体的应用示例:

[java]  view plain copy print ?
  1. try {   
  2. con = java.sql.DriverManager.getConnection(dbUrl,dbUser,dbPwd);   
  3. //设置手工提交事务模式   
  4. con.setAutoCommit(false);   
  5. stmt = con.createStatement();   
  6. //数据库更新操作1   
  7. stmt.executeUpdate("update ACCOUNTS set BALANCE=900 where ID=1 ");   
  8. //数据库更新操作2   
  9. stmt.executeUpdate("update ACCOUNTS set BALANCE=1000 where ID=2 ");   
  10. con.commit(); //提交事务   
  11. }catch(Exception e) {   
  12. try{   
  13. con.rollback(); //操作不成功则撤销事务   
  14. }catch(Exception ex){   
  15. //处理异常   
  16. ……   
  17. }   
  18. //处理异常   
  19. ……   
  20. }finally{…}   


       看到上边的示例我们可以看出,其实hibernate事务边界就是模仿者JDBC的事务边界来的,其实在hibernate底层的事务管理就是利用的JDBC的事务管理。我们来看一下hibernate事务边界:

1.声明事务的开始边界: 

Transaction tx=session.beginTransaction(); 

2.提交事务: tx.commit(); 

3.撤销事务: tx.rollback(); 

       我们在学习JDBC数据库事务管理的时候,重点也是难点的学习了jdbc多个事务并发问题。既然hibernate底层是用JDBC事务管理实现的,那么它也一定存在着多个事务并发的问题。下面我们就具体来看一下:hibernate多个事务并发的并发问题:

•第一类丢失更新:撤销一个事务时,把其他事务已提交的更新数据覆盖。 

•脏读:一个事务读到另一事务未提交的更新数据。 

•虚读:一个事务读到另一事务已提交的新插入的数据。 

•不可重复读:一个事务读到另一事务已提交的更新数据。 

•第二类丢失更新:这是不可重复读中的特例,一个事务覆盖另一事务已提交的更新数据。 

下面我们就脏读来举一个示例:

                                            

取款事务在T5时刻把存款余额改为900元,支票转账事务在T6时刻查询账户的存款余额为900元,取款事务在T7时刻被撤销,支票转账事务在T8时刻把存款余额改为1000元。 由于支票转账事务查询到了取款事务未提交的更新数据,并且在这个查询结果的基础上进行更新操作,如果取款事务最后被撤销,会导致银行客户损失100元。 

事务隔离级别

关于事务隔离级别,我们来看一下下面的两个图解:

                                  

                                    

由上图可以看出:隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。 对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed,它能够避免脏读,而且具有较好的并发性能。尽管它会导致不可重复读、虚读和第二类丢失更新这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。 

下面我们就具体来看一下hibernate怎么来配置隔离级别:在Hibernate的配置文件中可以显式的设置隔离级别。每一种隔离级别都对应一个整数: 

1:Read Uncommitted 

2:Read Committed 

4:Repeatable Read 

8:Serializable 

例如,以下代码把hibernate.cfg.xml文件中的隔离级别设为Read Committed: 

hibernate.connection.isolation=2 

对于从数据库连接池中获得的每个连接,Hibernate都会把它改为使用Read Committed隔离级别。 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值