1

どういうわけか、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 の「内部」には、Statement または PreparedStatements を使用するメソッドがあります (複数の PreparedStatement がある場合があります)。例:clear()メソッドで を使用statement.addBatch("DELETE FROM table;")したい、insert(...)メソッドで特別な PreparedStatement を使用して SQLINSERT操作を実行しdoSomethingElse(...)たい、別の PreparedStatement を別のものに使用したい、など。

呼び出された順序でこのステートメントを実行するにはどうすればよいmyTable.execute()ですか?

4

2 に答える 2

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;

  }
}

次のように、DBEngine Bean の内部にある実際のバッチ準備セクションで k をインクリメントする必要があります。

    //------------------------------------------
     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) を呼び出して、残ったものをすべてバッチ処理します。

注: このソリューションは AutoCommit(true) を使用します

于 2013-11-30T17:40:53.497 に答える
0

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

于 2012-04-25T12:26:13.237 に答える