webentwicklung-frage-antwort-db.com.de

Zwei verschiedene vorbereitete Anweisungen in einer einzelnen Charge

Ich möchte zwei verschiedene vorbereitete Anweisungen in einer einzigen Charge senden

Zur Zeit mache ich dies in zwei Schritten, wie Sie in den kommentierten Zeilen sehen können und es funktioniert, aber das ist hier nicht das Hauptziel. Kann mir jemand sagen, was ich an Stelle dieser Kommentare setzen muss, damit dieses Ding funktioniert?

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;
    }
}
14
gmustudent

Sie können nicht zwei verschiedene Anweisungen in einem einzelnen Stapel ausführen. Wie @dan erwähnt, können Sie - und müssen - in einer einzigen Transaktion ausführen.

Eine andere Option ist die Verwendung einer gespeicherten Prozedur, die alles in einem einzigen Roundtrip zum Server erledigen kann, während die Vorteile einer einzelnen Transaktion erhalten bleiben

7

Sie können versuchen, die beiden Anweisungen auszuführen, wie folgt:

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

Das Problem ist, dass addBatch mit einer einzelnen vorbereiteten Anweisung funktioniert, siehe das ist wie Sie mehrere SQL-Anweisungen mit addBatch verwenden können.

9
dan

Ich versuche, vorbereitete Anweisungen und einen Batch zu verwenden! Ich sage Anweisungen, weil ich zwei vorbereitete Anweisungen in einer Charge senden möchte.

Wenn Sie von PreparedStatement sprechen, ist ein Stapel mit dem Stapel von Befehlen dieses PreparedStatement-Objekts verknüpft undNICHTund umgekehrt. Sie sollten sich die Methode javadoc for addBatch() anschauen, um mehr darüber zu erfahren.

In Ihrem Fall hätte ich Folgendes getan:

  • Eine neue Transaktion wurde erstellt und ein Stapellimit festgelegt
  • Es wurde ein Satz von Stapeln für jedes PreparedStatement erstellt und ein Stapelzähler erhöht
  • Hat den Stapel ausgeführt, wenn ich das Limit erreicht habe und den Zähler zurückgesetzt habe
  • Hat meine Transaktion festgelegt, sobald ich fertig bin

Ihr Code würde also ungefähr so ​​aussehen:

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
}
2
Sujay

Ich denke, Sie möchten Ihre Anweisungsabfragen als eine zusammenführen und so etwas tun:

 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();
0
Yogendra Singh