Eu segui todas as respostas desta pergunta para alterar um código legado em funcionamento usando - Statement
(mas com injeções SQL) para uma solução usando PreparedStatement
um código muito mais lento por causa do fraco entendimento da semântica em torno do Statement.addBatch(String sql)
& PreparedStatement.addBatch()
.
Então, estou listando meu cenário aqui para que outros não cometam o mesmo erro.
Meu cenário foi
Statement statement = connection.createStatement();
for (Object object : objectList) {
//Create a query which would be different for each object
// Add this query to statement for batch using - statement.addBatch(query);
}
statement.executeBatch();
Portanto, no código acima, eu tinha milhares de consultas diferentes, todas adicionadas à mesma instrução e esse código funcionava mais rápido porque as instruções que não estavam sendo armazenadas em cache eram boas e esse código era executado raramente no aplicativo.
Agora, para corrigir as injeções de SQL, alterei esse código para,
List<PreparedStatement> pStatements = new ArrayList<>();
for (Object object : objectList) {
//Create a query which would be different for each object
PreparedStatement pStatement =connection.prepareStatement(query);
// This query can't be added to batch because its a different query so I used list.
//Set parameter to pStatement using object
pStatements.add(pStatement);
}// Object loop
// In place of statement.executeBatch(); , I had to loop around the list & execute each update separately
for (PreparedStatement ps : pStatements) {
ps.executeUpdate();
}
Entenda, comecei a criar milhares de PreparedStatement
objetos e, eventualmente, não consegui utilizar lotes porque meu cenário exigia isso - existem milhares de consultas UPDATE ou INSERT e todas essas consultas são diferentes.
A correção da injeção de SQL era obrigatória sem nenhum custo de degradação do desempenho e não acho que isso seja possível PreparedStatement
nesse cenário.
Além disso, ao usar o recurso de lote embutido, você precisa se preocupar em fechar apenas uma instrução, mas com essa abordagem da lista, é necessário fechar a instrução antes de reutilizá-la, reutilizando uma declaração preparada