2012-04-25 11 views
0

PreparedStatementバッチとStatementバッチを混在させて、両方を単一のトランザクションで実行することは可能ですか?PreparedStatementバッチとStatementバッチを混在させることは可能ですか?

私が持っているのは、トランザクションを表す自分のデータアクセスオブジェクトです。 StatementまたはPreparedStatementsのを(複数のPreparedStatementがあるかもしれません)を使用する方法があるMyTableTransactionObjectの「ボンネットの下に」

/* 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(); 

:私はこのようにそれを使用したいと思います。

など、 clear()方法で、私は doSomethingElse(...)に、私は何か他のもののために別のPreparedStatementを使用したい、 insert(...)方法で、私はSQL INSERT操作を実行するために特別なPreparedStatementを使用したい、 statement.addBatch("DELETE FROM table;")を使用したいどのように実行を実現することができます。たとえば、彼らは myTable.execute()で呼ばれたのですか?

+0

MySQLを使用している場合は、ドライバレベルでrewriteBatchedStatementsを有効にしてください:http://dev.mysql.com/doc/refman/5.5/en /connector-j-reference-configuration-properties.html –

答えて

0

Statements/PreparedStatementsが共通のConnectionを共有していて、そのConnectionでトランザクションをコミットしない場合、共通のトランザクションを共有します。

+0

したがって、addBatch()の後にexecuteBatch()を呼び出すか、複数のaddBatch()のブロックの後に(AutoCommitがfalseに設定されていると仮定して)何の違いはありませんか? – Mixer

+0

は現在のトランザクションの点では問題ありません。 executeBatch()をあまり頻繁に呼び出さないと(データベースへのラウンドトリップが少ないため)、パフォーマンスが向上することに注意してください。 – jtahlborn

1

これは最も洗練された解決策ではありません。パフォーマンスは%$#から払いますが、機能します。

あなたが好きなあなたは、DBEngine豆の内部 であなたの実際のバッチ作成部でのkをインクリメントする必要が
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; 

    } 
} 

:実際の実装は、あなたがのインスタンスをインスタンス化した別のコードである

//------------------------------------------ 
    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を再作成しなければならないということです。 – adv

関連する問題