Два разных подготовленных заявления в одной партии
Я хочу отправить два разных подготовленных оператора в одну партию.
В настоящее время я делаю это пополам, как вы можете видеть в комментариях, и это работает, но это не главная цель здесь. Может ли кто-нибудь сказать мне, что добавить эти комментарии, чтобы заставить эту работу работать?
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;
}
}
Ответы
Ответ 1
Вы не можете выполнять два разных оператора в одной партии. Как сказал @dan, вы можете - и должны - выполнять их в одной транзакции.
Другой вариант - использовать хранимую процедуру, которая может сделать все это в одном обращении к серверу, сохраняя при этом преимущества одной транзакции
Ответ 2
Вы можете попробовать выполнить два оператора - это одна транзакция, например:
connection.setAutoCommit(false);
try {
stmt1.execute();
stmt2.execute();
connection.commit();
} catch (Exception ex) {
connection.rollback();
}
Проблема заключается в том, что addBatch работает с одним подготовленным оператором, см. это, как вы можете использовать несколько операторов sql с addBatch.
Ответ 3
Я пытаюсь использовать подготовленные заявления и пакет! Я говорю потому что я хотел бы отправить два подготовленных заявления в один партии.
Когда вы говорите о PreparedStatement, пакетный пакет ассоциирован с этим пакетом команд PreparedStatement и NOT в обратном порядке. Вы должны посмотреть javadoc для метода addBatch()
, чтобы узнать больше об этом.
Итак, в вашем случае, вот что я сделал бы:
- Создал новую транзакцию и установил лимит пакетов
- Создал набор пакетов для каждого PreparedStatement и увеличил счетчик партий
- Выполняет пакет, когда я нажимаю предел и reset счетчик
- Я совершил транзакцию, когда я закончил.
Итак, ваш код будет выглядеть примерно так:
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
Я думаю, вы можете объединить свои запросы с запросами как один и сделать что-то вроде этого:
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();