20

2つの異なるプリペアドステートメントを1つのバッチで送信したいと思います。

コメント行でわかるように、現在私はこれを2つに分けて行っており、機能しますが、それはここでの主な目的ではありません。誰かがこのことを機能させるためにそれらのコメントの代わりに何を置くべきか教えてもらえますか?

import java.lang.ClassNotFoundException;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.DriverManager;

public class Main
{
    public static void main(String[] args)
    {
        Connection connection = null;
        PreparedStatement preparedStatementWithdraw = null;
        PreparedStatement preparedStatementDeposit = null;

        try
        {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/youtube", "root", "root");

            preparedStatementWithdraw = withdrawFromChecking(connection, preparedStatementWithdraw, new BigDecimal(100), 1);
            preparedStatementDeposit = depositIntoSaving(connection, preparedStatementDeposit, new BigDecimal(300), 1);

            //preparedStatementDeposit.executeBatch();
            //preparedStatementWithdraw.executeBatch();
            System.out.println("Account Modified!");
        }
        catch(ClassNotFoundException error)
        {
            System.out.println("Error: " + error.getMessage());
        }
        catch(SQLException error)
        {
            System.out.println("Error: " + error.getMessage());
        }
        finally
        {
            if(connection != null) try{connection.close();} catch(SQLException error) {}
            if(preparedStatementDeposit != null) try{preparedStatementDeposit.close();} catch(SQLException error) {}
        }
    }

    public static PreparedStatement withdrawFromChecking(Connection connection, PreparedStatement preparedStatement, BigDecimal balance, int id) throws SQLException
    {
        preparedStatement = connection.prepareStatement("UPDATE bankAccount SET checkingBalance = checkingBalance - ? WHERE id = ?");
        preparedStatement.setBigDecimal(1, balance);
        preparedStatement.setInt(2, id);
        preparedStatement.addBatch();

        return preparedStatement;
    }

    public static PreparedStatement depositIntoSaving(Connection connection, PreparedStatement preparedStatement, BigDecimal balance, int id) throws SQLException
    {
        preparedStatement = connection.prepareStatement("UPDATE bankAccount SET savingBalance = savingBalance + ? WHERE id = ?");
        preparedStatement.setBigDecimal(1, balance);
        preparedStatement.setInt(2, id);
        preparedStatement.addBatch();

        return preparedStatement;
    }
}
4

4 に答える 4

10

次のように、2つのステートメントを1つのトランザクションで実行してみることができます。

connection.setAutoCommit(false);
try {
    stmt1.execute();
    stmt2.execute();
    connection.commit();
} catch (Exception ex) {
    connection.rollback();
}

問題は、addBatchが単一のプリペアドステートメントで機能することです。これが、addBatchで複数のSQLステートメントを使用する方法です。

于 2012-10-19T15:34:08.293 に答える
10

1つのバッチで2つの異なるステートメントを実行することはできません。@danが述べたように、単一のトランザクションでそれらを実行でき、実行する必要があります。

もう1つのオプションは、単一のトランザクションの利点を維持しながら、サーバーへの単一のラウンドトリップですべてを実行できるストアドプロシージャを使用することです。

于 2012-10-19T15:39:56.140 に答える
1

プリペアドステートメントとバッチを活用しようとしています!2つの準備されたステートメントを1つのバッチで送信したいので、ステートメントと言います。

PreparedStatementについて話している場合、バッチはこのPreparedStatementオブジェクトのコマンドのバッチに関連付けられており、その逆ではありません。これについて詳しく知るには、メソッドのjavadocを参照する必要があります。addBatch()

だからあなたの場合、これが私がしたであろうことです:

  • 新しいトランザクションを作成し、バッチ制限を設定しました
  • PreparedStatementごとにバッチのセットを作成し、バッチカウンターをインクリメントします
  • 制限に達してカウンターをリセットしたときにバッチを実行しました
  • 完了したらトランザクションをコミットしました

したがって、コードは次のようになります。

preparedStatementWithdraw = connection.prepareStatement(....);
preparedStatementDeposit  = connection.prepareStatement(....);
boolean autoCommit        = connection.getAutoCommit();

int batchLimit = 1000; //limit that you can vary
int batchCounter = 0;
try{
    connection.setAutoCommit(false);

    //set the params and start adding your batch statements, as per your requirement, something like
    preparedStatementWithdraw.addBatch();
    preparedStatementDeposit.addBatch();
    batchCounter++;

    if(batchCounter == batchLimit){
        try{
            preparedStatementWithdraw.executeBatch();
            preparedStatementDeposit.executeBatch();
        }catch(Exception exe){
            //log your error
        }finally{
            preparedStatementWithdraw.clearBatch();
            preparedStatementDeposit.clearBatch();
            batchCounter = 0;
        }
    }
}finally{
        //process if any more statements are remaining in the batch
        try{
            preparedStatementWithdraw.executeBatch();
            preparedStatementDeposit.executeBatch();
        }catch(Exception exe){
            //log your error
        }finally{
            preparedStatementWithdraw.clearBatch();
            preparedStatementDeposit.clearBatch();
        }

    //1. depending on your requirement, commit/rollback the transation
    //2. Set autocommit to its original value
    connection.setAutoCommit(autoCommit);
    //3. Resoure management statements
}
于 2012-10-19T15:41:55.843 に答える
0

ステートメントクエリを1つにマージして、次のようなことを行うことをお勧めします。

 String updateAccount= "UPDATE bankAccount 
                      SET if(? is not null ) 
                        then checkingBalance = checkingBalance - ? end if, 
                        if(? is not null ) 
                         then savingBalance = savingBalance + ? end if
                      WHERE id = ?";                
 PreparedStatement = dbConnection.prepareStatement(updateAccount);

 preparedStatement.setDouble(1, new Double(100));
 preparedStatement.setDouble(2, new Double(100));
 preparedStatement.setDouble(3, null);
 preparedStatement.setDouble(4, null);
 preparedStatement.setInt(5, 1);
 preparedStatement.addBatch();

 preparedStatement.setDouble(1, null);
 preparedStatement.setDouble(2, null);
 preparedStatement.setDouble(3, new Double(100));
 preparedStatement.setDouble(4, new Double(100));
 preparedStatement.setInt(5, 1);
 preparedStatement.addBatch();
 preparedStatement.executeBatch();

 dbConnection.commit();
于 2012-10-19T15:52:18.977 に答える