Je veux envoyer deux déclarations préparées différentes en un seul lot .
Actuellement, je le fais en deux comme vous pouvez le voir dans les lignes commentées et cela fonctionne, mais ce n'est pas l'objectif principal ici. Quelqu'un peut-il me dire quoi mettre en place de ces commentaires pour que cette chose fonctionne?
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;
}
}
Vous ne pouvez pas exécuter deux instructions différentes dans un même lot. Comme @dan l’a mentionné, vous pouvez - et devez - les effectuer en une seule transaction.
Une autre option consiste à utiliser une procédure stockée qui peut tout faire en un seul aller-retour vers le serveur tout en conservant les avantages d'une transaction unique.
Vous pouvez essayer d'exécuter les deux instructions en une seule transaction, comme ceci:
connection.setAutoCommit(false);
try {
stmt1.execute();
stmt2.execute();
connection.commit();
} catch (Exception ex) {
connection.rollback();
}
Le problème est que addBatch fonctionne sur une seule instruction préparée, voir ceci est comment utiliser plusieurs instructions SQL avec addBatch.
J'essaie d'utiliser des déclarations préparées et un lot! Je dis déclarations parce que je voudrais envoyer deux déclarations préparées dans un lot.
Lorsque vous parlez de PreparedStatement, un lot est associé au lot de commandes de cet objet PreparedStatement _ et PAS à l'inverse. Vous devriez regarder la méthode javadoc pour addBatch()
pour en savoir plus à ce sujet.
Donc, dans votre cas, voici ce que j'aurais fait:
Donc, votre code ressemblerait à quelque chose comme ça:
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
}
Je pense que vous voudrez peut-être fusionner vos requêtes de relevé et faire quelque chose comme ceci:
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();