【问题标题】:Two different prepared statements in one single batch一个批次中有两个不同的准备好的语句
【发布时间】:2012-10-10 06:20:05
【问题描述】:

我想在一个批次中发送两个不同的准备好的语句

目前,正如您在注释行中看到的那样,我正在分两步执行此操作,并且它有效,但这不是这里的主要目标。谁能告诉我用什么来代替那些 cmets 才能让这个东西工作?

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

【问题讨论】:

标签: java sql jdbc prepared-statement


【解决方案1】:

你可以尝试执行这两条语句是一个单一的事务,像这样:

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

问题在于 addBatch 在单个预准备语句上工作,请参阅 this is 如何将多个 sql 语句与 addBatch 一起使用。

【讨论】:

  • 想了想。如果有人在这里告诉我这是不可能的,那将是另一种选择。
  • 查看我更新的答案,问题是 addBatch 与单个准备好的语句相关联。
【解决方案2】:

我认为您可能希望将语句查询合并为一个并执行以下操作:

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

【讨论】:

    【解决方案3】:

    我正在尝试使用准备好的语句和批处理!我说 声明,因为我想将两个准备好的声明合二为一 批处理。

    当您谈到 PreparedStatement 时,批处理与此 PreparedStatement 对象的命令批处理相关联,而 NOT 则相反。您应该查看javadocaddBatch() 方法以了解更多信息。

    所以在你的情况下,我会这样做:

    • 创建了一个新事务并设置了批量限制
    • 为每个 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
    }
    

    【讨论】:

      【解决方案4】:

      您不能在一个批处理中执行两个不同的语句。正如@dan 提到的,您可以——并且必须——在单个事务中完成它们。

      另一种选择是使用存储过程,它可以在与服务器的一次往返中完成所有操作,同时保持单个事务的好处

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-02-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-03
        • 1970-01-01
        相关资源
        最近更新 更多