一批中有两种不同的预处理语句

时间:2012-10-19 15:29:23

标签: java sql jdbc prepared-statement

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

目前我在两个中这样做,你可以在注释行中看到并且它有效,但这不是这里的主要目标。任何人都可以告诉我应该用什么来代替这些评论来使这个东西起作用吗?

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 个答案:

答案 0 :(得分:9)

您可以尝试执行这两个语句是单个事务,如下所示:

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

问题是addBatch在单个预准备语句上工作,请参阅this is如何在addBatch中使用多个sql语句。

答案 1 :(得分:7)

您不能在一个批处理中执行两个不同的语句。正如@dan所提到的,你可以 - 并且必须 - 在一次交易中完成它们。

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

答案 2 :(得分:2)

  

我正在尝试使用预备语句和批处理!我说   语句因为我想在一个语句中发送两个准备好的语句   批次。

当您谈论 PreparedStatement 时,批处理与此 PreparedStatement 对象的批处理命令相关联,而 NOT 则相反。您应该查看addBatch() 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 } 方法以了解更多相关信息。

所以在你的情况下,这就是我要做的事情:

  • 创建新事务并设置批量限制
  • 为每个PreparedStatement创建一组批处理并增加批处理计数器
  • 达到限制时执行批处理并重置计数器
  • 一旦我完成了承诺我的交易

所以你的代码看起来像这样:

{{1}}

答案 3 :(得分:0)

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

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