I want to send two different prepared statements in one single batch.
Currently I am doing this in two as you can see in the commented lines and it works, but that is not the main objective here. Can anyone tell me what to put in place of those comments to get this thing to work?
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;
}
}
Once a PreparedStatement is prepared, it can be reused after execution. You reuse a PreparedStatement by setting new values for the parameters and then execute it again.
Following are the limitations of prepared statements: Since a PreparedStatement object represents only one SQL statement at a time, we can execute only one statement by one prepared statement object. To prevent injection attacks it does not allow more than one value to a place holder.
Grouping a set of INSERT Statements and executing them at once is known as batch insert.
Statement – Used to execute string-based SQL queries. PreparedStatement – Used to execute parameterized SQL queries.
You cannot execute two different statements in a single batch. As @dan mentioned you can -- and must -- do them in a single transaction.
Another option is to use a stored procedure that can do it all in a single roundtrip to the server while maintaining the benefits of single transaction
You can try execute the two statement is a single transaction, like this:
connection.setAutoCommit(false);
try {
stmt1.execute();
stmt2.execute();
connection.commit();
} catch (Exception ex) {
connection.rollback();
}
The issue is that addBatch works on a single prepared statement, see this is how you can use multiple sql statements with addBatch.
I am trying to utilize prepared statements and a batch! I say statements because I would like to send two prepared statements in one batch.
When you're talking of PreparedStatement, a batch is associated with this PreparedStatement object's batch of commands and NOT the other way round. You should look at the javadoc for addBatch()
method to know more about this.
So in your case, here's what I would have done:
So your code would look something like this:
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With