A Joana colocou a seguinte pergunta sobre Statement vs PreparedStatement no artigo JDBC: Acessando Bancos de Dados em Java:
Olá professor,
Quais são as diferenças entre Statement e prepareStatement?
E, ao invés de responder diretamente no comentário, achei que a resposta valia um post! 🙂
Conceito
Bom, vamos direto ao ponto: a principal diferença entre o Statement e o PreparedStatement é que o PreparedStatement é “preparado” no banco de dados, tornando-o mais rápido. Ou seja, se você fizer diversas consultas parecidas, onde só mudam alguns valores, ele executa mais rapidamente do que se você fizer várias consultas usando o Statement.
Isso acontece porque quando uma consulta chega no banco de dados para ser executada, ela tem que passar por diversos passos de preparação até ser realmente processada. Ao usar o Statement, esses passos são feitos a cada consulta. Já no PreparedStatement, esses passos são feitos apenas uma vez.
Vamos ver um exemplo: imagine que você quer fazer as seguintes consultas:
insert into usuarios (nome, idade) values ('Amanda', 35); insert into usuarios (nome, idade) values ('Bruno', 22); insert into usuarios (nome, idade) values ('Carlos', 29);
Statement
Você pode criar um Statement e chamar o método executeUpdate para cada uma das consultas, assim:
Statement stmt = conn.createStatement(); stmt.executeUpdate("insert into usuarios (nome, idade) values ('Amanda', 35)"); stmt.executeUpdate("insert into usuarios (nome, idade) values ('Bruno', 22)"); stmt.executeUpdate("insert into usuarios (nome, idade) values ('Carlos', 29)");
PreparedStatement
Ou, então, criar um PreparedStatement que será enviado para o banco de dados e que, por sua vez, irá fazer todos os passos de preparação antes da execução definitiva. Logo após, basta mudar os valores das variáveis (?) e enviá-las para execução no banco, assim:
PreparedStatement stmt = conn.prepareStatement("insert into usuarios (nome, idade) values (?, ?)"); stmt.setString(1, "Amanda"); stmt.setString(2, "35"); stmt.executeUpdate(); stmt.setString(1, "Bruno"); stmt.setString(2, "22"); stmt.executeUpdate(); stmt.setString(1, "Carlos"); stmt.setString(2, "29"); stmt.executeUpdate();
Lógico que você não irá notar muita diferença de velocidade ao enviar apenas três consultas para o banco de dados, mas se você estiver fazendo isso muuuuuitas vezes, o PreparedStatement pode ajudar.
Fazendo um teste com a inserção de 1.000.000 usuários em uma tabela similar à do exemplo, obtive os seguintes resultados:
Tipo | Tempo Total (ms) | Tempo Total (min) | Tempo por Consulta (ms) |
---|---|---|---|
Statement | 714386 | 11,9 | 0,714 |
PreparedStatement | 657988 | 10,9 | 0,658 |
Isso significa que, no meu teste, o PreparedStatement foi aproximadamente 7,9% mais rápido que o Statement!
SQL Injection
É interessante notar que, para que você possa mudar os valores, o PreparedStatement tem esse mecanismos de alteração dos valores por meio dos métodos setString, setInt, etc. Isso traz um efeito colateral benéfico que é prevenir ataques de SQL Injection, uma vez que esses métodos fazem o tratamento dos valores sendo enviados.
Conclusão
Se você for fazer muitas consultas onde apenas os valores mudam, use o PreparedStatement. Se não for o caso, use o PreparedStatement mesmo assim, para evitar ataques de SQL Injection. 🙂
Até a próxima!