JDBC的PreparedStatement啟動事務使用批處理executeBatch()

來源:互聯網
上載者:User

標籤:

JDBC使用MySQL處理大資料的時候,自然而然的想到要使用批處理,

普通的執行過程是:每處理一條資料,就訪問一次資料庫;

而批處理是:累積到一定數量,再一次性提交到資料庫,減少了與資料庫的互動次數,所以效率會大大提高

至於事務:事務指邏輯上的一組操作,組成這組操作的各個單元,要不全部成功,要不全部不成功,預設是關閉事務的。

              更多事務的資料,請參考這裡:http://blog.csdn.net/caomiao2006/article/details/22412755

 

1. PreparedStatement使用批處理 executeBatch()       1.1. 不使用executeBatch(),而使用executeUpdate()

          代碼如下:  

         Class.forName("com.mysql.jdbc.Driver");
         Connection conn = DriverManager.getConnection(dbUrl, user, password);
         PreparedStatement pstmt = conn.prepareStatement("update content set introtext=? where id=?");

         for(int i=0; i<10000; i++){
             pstmt.setString(1, "abc"+i);
             pstmt.setInt(2, id);
             pstmt.executeUpdate();
         }

         這樣,更新10000條資料,就得訪問資料庫10000次

      1.2. 而使用executeBatch()

          代碼如下:

         Class.forName("com.mysql.jdbc.Driver");
         Connection conn = DriverManager.getConnection(dbUrl, user, password);
         PreparedStatement pstmt = conn.prepareStatement("update content set introtext=? where id=?");

         for(int i=0; i<10000; i++){
             pstmt.setString(1, "abc"+i);
             pstmt.setInt(2, id);
             pstmt.addBatch();//添加到同一個批處理中
         }

         pstmt.executeBatch();//執行批處理

 

         注意:1. 如果使用了 addBatch() -> executeBatch() 還是很慢,那就得使用到這個參數了

                      rewriteBatchedStatements=true (啟動批處理操作)

                      在資料庫連接URL後面加上這個參數:      

                          String dbUrl =  "jdbc:mysql://localhost:3306/User? rewriteBatchedStatements=true";

                      2. 在代碼中,pstmt的位置不能亂放,

                          //必須放在迴圈體外

                     pstmt = conn.prepareStatement("update content set introtext=? where id=?");

                     for(int i=0; i<10000; i++){

                           //放這裡,批處理會執行不了,因為每次迴圈重建了pstmt,不是同一個了

                           //pstmt = conn.prepareStatement("update content set introtext=? where id=?");
                           pstmt.setString(1, "abc"+i);
                           pstmt.setInt(2, id);
                           pstmt.addBatch();//添加到同一個批處理中
                     }

                     pstmt.executeBatch();//執行批處理

2. 啟用交易處理

          Class.forName("com.mysql.jdbc.Driver");

 

          Connection conn = DriverManager.getConnection(dbUrl, user, password);

          conn.setAutoCommit(false);//將自動認可關閉
          PreparedStatement pstmt = conn.prepareStatement("update content set introtext=? where id=?");
          pstmt.setString(1, tempintrotext);
          pstmt.setInt(2, id);
          pstmt.addBatch();
          pstmt.executeBatch();
          pstmt.close();


          conn.commit();//執行完後,手動提交事務
          conn.setAutoCommit(true);//在把自動認可開啟
          conn.close();

3. 事務和批處理混合使用      

          Class.forName("com.mysql.jdbc.Driver");

          Connection conn = DriverManager.getConnection(dbUrl, user, password);

          conn.setAutoCommit(false);//將自動認可關閉
          PreparedStatement pstmt = conn.prepareStatement("update content set introtext=? where id=?");

          for(int i=0; i<1000000; i++){
               pstmt.setString(1, tempintrotext);
               pstmt.setInt(2, id);
               pstmt.addBatch();

               //每500條執行一次,避免記憶體不夠的情況,可參考,Eclipse設定JVM的記憶體參數

               if(i>0 && i%500==0){
                    pstmt.executeBatch();

                    //如果不想出錯後,完全沒保留資料,則可以沒執行一次提交一次,但得保證資料不會重複

                    conn.commit();

                }

         }
          pstmt.executeBatch();//執行最後剩下不夠500條的
          pstmt.close();

          conn.commit();//執行完後,手動提交事務
          conn.setAutoCommit(true);//在把自動認可開啟
          conn.close();

 較完整的代碼:

 1 public class ExecuteBatchTest { 2     private Connection conn; 3     private PreparedStatement pstmt; 4     private PreparedStatement pstmt2; 5     private ResultSet rs; 6     private String user = "root"; 7     private String password = "123456"; 8     private String dbUrl = "jdbc:mysql://localhost:3306/user?rewriteBatchedStatements=true"; 9     private int limitNum = 10000;10 11     public void changeData() {12         try {13             Class.forName("com.mysql.jdbc.Driver");14             conn = DriverManager.getConnection(dbUrl, user, password);15             16             //既不用batch,也不用事務17             testBatch(false,false);18             //只用batch, 不用事務19             testBatch(false,true);20             //只用事務,不用batch21             testBatch(true,false);22             //不僅用事務,還用batch23             testBatch(true,true);24             25             pstmt.close();26             conn.close();27         } catch (ClassNotFoundException e) {28             e.printStackTrace();29         } catch (SQLException e) {30             e.printStackTrace();31         }32     }33     34     public void testBatch(Boolean openTransaction, Boolean useBatch) throws SQLException{35         if(openTransaction)36             conn.setAutoCommit(false);37         38         if(pstmt!=null){39             pstmt.clearParameters();40             pstmt.clearBatch();41         }42         43         pstmt = conn.prepareStatement("insert into person (name) values (?)");44         long start = System.currentTimeMillis();45         for(int a = 0;a<limitNum;a++){46             String name = "tommy"+a;47             pstmt.setString(1, name);48             if(useBatch)49                 pstmt.addBatch();50             else51                 pstmt.executeUpdate();52         }53         54         if(useBatch)55            pstmt.executeBatch();56          57         if(openTransaction){58             conn.commit();59             conn.setAutoCommit(true);60         }61         long end = System.currentTimeMillis();62         System.out.println("use time:"+(end-start)+" ms");63         64     }65     66     //main method67     publi static void main(String[] args){68         ExecuteBatchTest ebt = new ExecuteBatchTest();69         ebt.changeData();70     }71        72 }
View Code

運行結果:

   分別是: 不用批處理,不用事務;

               只用批處理,不用事務;

               只用事務,不用批處理;

               既用事務,也用批處理;(很明顯,這個最快,所以建議在處理大批量的資料時,同時使用批處理和事務)

 

JDBC的PreparedStatement啟動事務使用批處理executeBatch()

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.