2012-04-25 64 views
0

是否有可能以某種方式混合PreparedStatement批處理和Statement批處理,並保持雙方在單個事務中執行的好處?將PreparedStatement批處理與Statement批處理混合在一起,有可能嗎?

我有什麼是我自己的數據訪問對象,它代表事務。我想用這樣的:

/* here transaction starts: object receive connection, etc. */ 
MyTableTransactionObject myTable = new MyTableTransactionObject(); 

myTable.clear(); 
myTable.insert(Row1); 
myTable.insert(Row2); 
myTable.insert(Row3); 
myTable.doSomethingElse(); 
myTable.insert(Row4); 

/* here transaction ends, batches are executed changes are commited, 
    statements are closed */ 
myTable.execute(); 
myTable.close(); 

「引擎蓋下」 MyTableTransactionObject的有using語句或預處理語句(可能有多個預處理語句)的方法。例如:在clear()方法我想用statement.addBatch("DELETE FROM table;"),在insert(...)方法我想用特殊的PreparedStatement執行SQL INSERT操作,在doSomethingElse(...)我想用不同的PreparedStatement做別的事情,等

我怎樣才能實現執行這些陳述爲了他們被稱爲myTable.execute()

+0

如果你使用MySQL,請確保您能夠在驅動程序級別rewriteBatchedStatements該解決方案使用自動提交(真實):http://dev.mysql.com/doc/refman/5.5/en /connector-j-reference-configuration-properties.html – 2012-04-26 03:13:13

回答

0

如果您的Statements/PreparedStatements共享一個公共Connection,並且您沒有在該Connection上提交事務,則它們將共享一個公共事務。

+0

因此,無論我在每個addBatch()之後還是在幾個addBatch()之後調用executeBatch()(假設AutoCommit設置爲false),都沒有什麼區別? – Mixer 2012-04-25 17:55:42

+0

是正確的,就當前交易而言無關緊要。請注意,如果您調用executeBatch()的頻率較低(因爲您的數據庫往返次數較少),您將獲得更好的性能表現。 – jtahlborn 2012-04-26 11:39:18

1

這不是最優雅的解決方案,您將付出%$#的表現,但它確實有效。

public class DBEngine { 

private final int defaultBatchSize = 1000; 

private Pool pool = null; 
private Connection con = null; 
private PreparedStatement ps = null; 
private ArrayList<PreparedStatement> globalBatch = new ArrayList<PreparedStatement>(); 
private int k = 0; //bean-wide batch counter 
private boolean debugMode = false; 
private PreparedStatement batchPs = null; 
//-------------------------------- 
DBEngine(){ 
    this.pool = new Pool(); 
    this.con = pool.getConnection(); 
    this.ps = null; 
    this.k = 0; //bean-wide batch counter 
} 
//------------- 
boolean mixedBatchTime(boolean force){ 
    return mixedBatchTime(defaultBatchSize, force); 
} 
//------------- 
boolean mixedBatchTime(int customBatchSize){ 
    return mixedBatchTime(customBatchSize, false); 
} 
//------------- 
boolean mixedBatchTime(){ 
    return mixedBatchTime(defaultBatchSize, false); 
} 
//------------- 
// Executes a mixed batch of PreparedStatements 
//------------- 
boolean mixedBatchTime(int customBatchSize, boolean force){ 


    if(k > customBatchSize - 1 || force){ 
     try { 
      StringBuilder sqlStmt = new StringBuilder(); 

      for(int i = 0; i < globalBatch.size(); i++){ 
       sqlStmt.append(globalBatch.get(i) + "; "); 
      } 

      batchPs = con.prepareStatement(sqlStmt.toString());  
      batchPs.execute(); 
      ps = null; 
      sqlStmt = null; 
      batchPs = null; 
     } catch (SQLException e) { 
      e.printStackTrace(); 
     } 
     k = 0; 
     globalBatch = null; 
     globalBatch = new ArrayList<PreparedStatement>(); 
     return true; 
    }else return false; 

    } 
} 

你必須增加K的實際批准備部分即你用到dbengine豆喜歡裏面:

//------------------------------------------ 
    boolean updateSomeQuantity(int someID, int someQuantity){ 

     try{ 
      // detects if the statement has changed in order to recompile it only once per change 
      if(ps!=null && !ps.toString().contains("UPDATE sometable SET somequantity =")){ 
       ps = null; 
       String updateStmt = "UPDATE sometable SET somequantity = ? WHERE someID = ?"; 
       ps = con.prepareStatement(updateStmt); 
      }else if(ps == null){ 
       String updateStmt = "UPDATE sometable SET somequantity = ? WHERE someID = ?"; 
       ps = con.prepareStatement(updateStmt); 
      } 

      ps.setInt(1, someQuantity) 
      ps.setInt(2, someID); 

      globalBatch.add(ps); 
      k++; // very important 

      return true; 

     } catch (SQLException e) { 
      e.printStackTrace(); 
      if(e.getNextException() != null) e.getNextException().printStackTrace(); 
      return false; 
      } 
    } 

實際的實現是另一碼您實例的實例DBEngine bean,並在循環中使用updateSomeQuantity(somequantity)方法以及mixedBatchTime()方法。循環結束後,調用mixedBatchTime(true)來批處理剩餘的任何內容。

注:

+0

@jtahlborn:您可以在方法重載中向bean引擎指定一個自定義的批量大小。主要問題和性能受損的地方在於,每次更改「主題」時,必須重新使用PreparedStatements來重新使用PreparedStatements。 – adv 2014-01-07 16:11:08