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:
[code lang=”sql”]
insert into usuarios (nome, idade) values (‘Amanda’, 35);
insert into usuarios (nome, idade) values (‘Bruno’, 22);
insert into usuarios (nome, idade) values (‘Carlos’, 29);
[/code]
Statement
Você pode criar um Statement e chamar o método executeUpdate para cada uma das consultas, assim:
[code lang=”java”]
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)");
[/code]
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:
[code lang=”java”]
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();
[/code]
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!