数据库事务备忘录之二

      上一篇提到了数据库事务的ACID特性,那么谁来保证数据库事务具有ACID呢?其实,只要向数据库系统声明一个事务,数据库系统就会自动保证事务的ACID特性的。那么下面从抽象的概念上来看看怎么声明事务:
      -----  BEGIN 事务的开始边界
      -----  COMMIT 事务的正常结束边界,提交事务,永久保存被事务更新后的数据库状态。
      -----  ROLLBACK 事务的异常结束边界,撤销事务,使数据退回到执行事务前的初始状态。
      数据库系统支持以下两种事务模式:
      ----- 自动提交模式:每个SQL语句都是一个独立的事务,当数据库系统执行完一个SQL语句后,会自动提交事务。
      ----- 手工提交事务:必须由数据库的客户端显式指定事务开始边界和结束边界。
     以MySQL为例,如果我们启动一个MySQL客户端,就会得到一个独立的数据库连接。每个数据库连接都有一个全局变量@@autocommit,表示当前的事务模式,它有两个可选值:
      ----- 0:表示手工提交模式。
      ----- 1:默认值,表示自动提交模式

      可以通过SQL命令 SELECT @@autocommit 来查看当前的事务模式。如果想要把当前的事务模式改为手工提交模式,可以使用以下SQL命令  SET autocommit=0 来实现。
      还要多说几句,在MySQL中,数据库表分为三种类型:INNODB、BDB、MyISAM。其中前两种类型的表支持数据库事务,而MyISAM类型的表不支持事务。在使用CREATE TABLE命令创建表时默认的类型为MyISAM,如果希望更改的话可以通过如下DLL来进行:
       ALTER TABLE table_name TYPE=INNODB;
       如果希望在创建时就指定表的类型,可以通过以下DLL来进行:
       CREATE TABLE table_name(
           .....
           .....
       ) TYPE=INNODB;
      好了,下面我们来看几个在实践应用程序中声明事务的模板。
   
1.在MySQL.exe客户端程序中声明事务
      我们以一条插入语句为例,当然如果是自动提交模式的话,每一个SQL语句都是一个单独的事务,我们直接运行以下语句就可以了:
          mysql>INSERT INTO qq_account VALUES('leon', 1000);
     下面我们看看在手动模式下的命令:
          mysql>SET autocommit=0;
          mysql>BEGIN;
          mysql>INSERT INTO qq_account VALUES('leon', 1000);
          mysql>COMMIT;
      这样一个事务就完成了,下面我们看一看如何撤销一个事务,很简单也许你已经猜到了吧
          mysql>BEGIN;
          mysql>INSERT INTO qq_account VALUES('leon', 1000);
          mysql>ROLLBACK;

2.在JDBC API中声明事务
      没有什么难度,我们直接来看看代码:

  1. Connection con = null;   
  2. Statement stmt = null;   
  3. try {   
  4.    con = DriverManager.getConnection(dbUrl,dbUser,dbPwd);   
  5.    //设置手工提交事务模式   
  6.    con.setAutoCommit(false);   
  7.    stmt = con.createStatement();   
  8.    stmt.executeUpdate("INSERT INTO qq_account VALUES ('leon', 1000)");   
  9.    //提交事务   
  10.    con.commit();   
  11. catch(SQLException e) {   
  12.    if(con != null) {   
  13.       try {   
  14.          //操作不成功则撤销事务   
  15.          con.rollback();         
  16.       } catch(SQLException e) {   
  17.          ......   
  18.       }   
  19.    }   
  20.    ......   
  21. finally {   
  22.    if(con != null) {   
  23.       try{   
  24.          if(stmt != null) {   
  25.             try {    
  26.                stmt.close();   
  27.             } catch(SQLException e) {   
  28.                ......   
  29.             }   
  30.          }   
  31.          con.close();   
  32.       } catch(SQLException e) {   
  33.          ......   
  34.       }    
  35.    }   
  36. }   

      没有什么可再说的了,代码详细得已经像是一篇技术文章了,需要注意的是对于新建的Connection实例来说,在默认的情况下采用自动提交的事务模式,通过方法 con.setAutoCommit(false)来设置手动提交模式。

3.在Hibernate API中声明事务
       Hibernate封装了JDBC API和JTA API,尽管应用程序可以绕过Hibernate API,直接通过JDBC API和JTA API来声明事务,但是这不利于跨平台的开发,下面我们只考虑Hibernate API的实现:

  1. Configuration config = new Configuration().configure();   
  2. SessionFactory factory = config.buildSessionFactory();   
  3. Session session = factory.openSession();   
  4. Transation tx = null;   
  5. try {   
  6.    //开始一个事务   
  7.    tx = session.beginTransaction();   
  8.    Account account = new Account("leon",1000);   
  9.    session.save(account);   
  10.    //提交事务   
  11.    tx.commit();   
  12. catch(HibernateException e) {   
  13.     if(tx != null) {   
  14.        try {   
  15.           //操作不成功则撤销事务   
  16.           tx.rollback();   
  17.        } catch(HibernateException e) {   
  18.           ......   
  19.        }   
  20.     }   
  21.     ......   
  22. finally {   
  23.     if(session != null) {   
  24.        try {   
  25.           session.close();   
  26.        } catch(HibernateException e) {   
  27.           ......   
  28.        }   
  29.     }   
  30. }  

      上面的代码和JDBC API很相像,值得注意的是,在任何时候,一个Session只允许有一个未提交的事务。以下代码对于一个Session同时声明了两个未提交的事务,这是不允许的:
          tx1 = session.beginTransaction();
          tx2 = session.beginTransaction();
                 ......
          tx1.commit();
          tx2.commit();
      好了,今天就写到这里吧,顺便唠叨一句,看到新的一期《程序员》里面的调查71%的程序员通过写技术BLOG提升自己的技术水平,坚定了自己作技术BLOG的信心,每天都记录下自己的学习轨迹,让自己更加的充实...  

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值