Cyh的博客

          Email:kissyan4916@163.com
          posts - 26, comments - 19, trackbacks - 0, articles - 220

          提交與回滾事務(wù)

          Posted on 2009-12-28 21:22 啥都寫點(diǎn) 閱讀(4201) 評(píng)論(0)  編輯  收藏 所屬分類: J2SE
               事務(wù)在提交前,所有的操作都是在虛擬的環(huán)境中進(jìn)行的,事務(wù)提交時(shí)才將事務(wù)進(jìn)行的所有修改更新到數(shù)據(jù)庫(kù)的存儲(chǔ)介質(zhì)上,如硬盤。在事務(wù)提交前,如果有操作失敗的情況,那么需要進(jìn)行回滾操作,便可以取消事務(wù)所進(jìn)行的修改,當(dāng)事務(wù)被提交后,再執(zhí)行回滾是無(wú)效的。
               事務(wù)需要數(shù)據(jù)庫(kù)的支持,不是所有的數(shù)據(jù)庫(kù)都執(zhí)行事務(wù),如MySQL中默認(rèn)的數(shù)據(jù)庫(kù)都采用了MyISAM存儲(chǔ)引擎,它不支持事務(wù),如果MySQL數(shù)據(jù)庫(kù)采用InnoDB存儲(chǔ)的引擎,便支持事務(wù)。通過(guò)DatabaseMetaData的supportsTransactions方法可以判斷數(shù)據(jù)庫(kù)是否支持事務(wù)。
               數(shù)據(jù)庫(kù)連接Connection對(duì)象默認(rèn)是自動(dòng)提交的,即在該連接下,每用Statement執(zhí)行一條SQL語(yǔ)句,便提交到數(shù)據(jù)庫(kù)。為了控制事務(wù)提交的時(shí)機(jī),需要在事務(wù)開始前,調(diào)用Connection的setAutoCommit方法將數(shù)據(jù)庫(kù)連接的自動(dòng)提交屬性關(guān)閉,此后,所有的操作都不會(huì)提交到數(shù)據(jù)庫(kù),直到調(diào)用Connection的commit方法,提交事務(wù)位置。
               在提交事務(wù)之前,一旦有SQL語(yǔ)句執(zhí)行不通過(guò),應(yīng)調(diào)用Connection的rollback方法,執(zhí)行回滾操作,那么此前所有數(shù)據(jù)庫(kù)操作將無(wú)效。


          import java.sql.Connection;
          import java.sql.DatabaseMetaData;
          import java.sql.SQLException;
          import java.sql.Statement;

          /**
           * 判斷數(shù)據(jù)庫(kù)是否支持事務(wù),如果支持,如何實(shí)現(xiàn)事務(wù)的提交與回滾。
           * MySQL中如果要使用事物,必須使用InnoDB存儲(chǔ)引擎,在創(chuàng)建表時(shí),后面加上ENGINE=InnoDB。
           * MySQL默認(rèn)的存儲(chǔ)引擎是MyISAM,不支持事物
           
          */

          public class Transaction {

              
          /**
               * 判斷數(shù)據(jù)庫(kù)是否支持事務(wù)
               * 
          @param con    數(shù)據(jù)庫(kù)的連接
               * 
          @return
               
          */

              
          public static boolean supportTransaction(Connection con){
                  
          try {
                      
          // 得到數(shù)據(jù)庫(kù)的元數(shù)據(jù)
                      DatabaseMetaData md = con.getMetaData();
                      
          return md.supportsTransactions();
                  }
           catch (SQLException e) {
                      e.printStackTrace();
                  }

                  
          return false;
              }

              
              
          /**
               * 將一組SQL語(yǔ)句放在一個(gè)事務(wù)里執(zhí)行,要某全部執(zhí)行通過(guò),要某全部不執(zhí)行
               * 
          @param con    數(shù)據(jù)庫(kù)的連接
               * 
          @param sqls    待執(zhí)行的SQL數(shù)組
               
          */

              
          public static void goTransaction(Connection con, String[] sqls){
                  
          if (sqls == null){
                      
          return ;
                  }

                  Statement sm 
          = null;
                  
          try {
                      
          // 事務(wù)開始
                      System.out.println("事務(wù)開始!");
                      
          // 設(shè)置連接不自動(dòng)提交,即用該連接進(jìn)行的操作都不更新到數(shù)據(jù)庫(kù)
                      con.setAutoCommit(false);
                      sm 
          = con.createStatement();
                      
          for (int i=0; i<sqls.length; i++){
                          
          // 執(zhí)行SQL語(yǔ)句,但是沒更新到數(shù)據(jù)庫(kù)
                          sm.execute(sqls[i]);
                      }

                      
          // 提交,立即更新到數(shù)據(jù)庫(kù)
                      System.out.println("事務(wù)提交!");
                      con.commit();
                      System.out.println(
          "事務(wù)結(jié)束!");
                      
          // 事務(wù)結(jié)束
                  }
           catch (SQLException e) {
                      
          try {
                          
          // 出現(xiàn)異常時(shí),進(jìn)行回滾,取消前面執(zhí)行的操作
                          System.out.println("事務(wù)執(zhí)行失敗,進(jìn)行回滾!");
                          con.rollback();
                      }
           catch (SQLException e1) {
                          e1.printStackTrace();
                      }

                  }
           finally {
                      OperateDB.closeStatement(sm);
                  }

              }

              
              
          public static void main(String[] args) throws ClassNotFoundException,
                      SQLException 
          {
                  String dbName 
          = "studentdb";
                  String userName 
          = "test";
                  String password 
          = "test";
                  String[] sqls 
          = new String[3];
                  sqls[
          0= "UPDATE student_basic_innodb SET score=93 where name='john'";
                  sqls[
          1= "INSERT INTO student_basic_innodb (name, age, score)"
                      
          + " VALUES ('zhangsan', 17, 86)";
                  
          // 執(zhí)行這條語(yǔ)句會(huì)引起錯(cuò)誤,因?yàn)楸韘tudent_basic_innodb沒有xxxxxxx列
                  sqls[2= "DELETE FROM student_basic_innodb where xxxxxxx='wade'";
                  
                  Connection con 
          = null;
                  
          try {
                      
          // 獲得數(shù)據(jù)庫(kù)連接
                      con = DBConnector.getMySQLConnection(nullnullnull, dbName,
                              userName, password);
                      
          // 判斷是否支持批處理
                      boolean supportTransaction = Transaction.supportTransaction(con);
                      System.out.println(
          "支持事務(wù)? " + supportTransaction);
                      
          if (supportTransaction){
                          
          // 執(zhí)行事務(wù)
                          Transaction.goTransaction(con, sqls);
                      }

                  }
           catch (ClassNotFoundException e1) {
                      
          throw e1;
                  }
           catch (SQLException e2) {
                      
          throw e2;
                  }
           finally {
                      
          // 關(guān)閉數(shù)據(jù)庫(kù)連接
                      OperateDB.closeConnection(con);
                  }

              }

          }


                                                                                                                 --    學(xué)海無(wú)涯
                  

          主站蜘蛛池模板: 太仓市| 阜平县| 晋州市| 延长县| 石阡县| 文成县| 全州县| 临漳县| 诏安县| 屯门区| 文登市| 叙永县| 大理市| 榆林市| 尼勒克县| 临湘市| 宁远县| 安远县| 鄢陵县| 霍山县| 修文县| 阳山县| 都昌县| 万安县| 宣恩县| 蛟河市| 肥乡县| 文昌市| 金溪县| 巍山| 六盘水市| 彭州市| 昔阳县| 策勒县| 甘南县| 鹤山市| 宜兰县| 无锡市| 永嘉县| 伊川县| 阳山县|