bom gente, bom dia a todos, me bateu um dia desses mais um dúvida newb que vou compartilhar aqui com vocês.
Estou fazendo umas classes para acessar e manipular o banco de dados. nestas, estou usando o PreparedStatement para substituir os caracteres coringas da minha query, e executar a mesma. Ou seja, estou usando o PreparedStatement para inserir algumas coisas no Banco de dados.
Entretanto, eu preciso agora recuperar algumas informações do meu Banco de dados. E eu pensei em fazer da seguinte forma:
[code]
public static List procurarLivro( String nome )
{
List livro = null;
try
{
String sql = “SELECT * FROM livro WHERE nome = ?”;
Conexao conexao = new Conexao("jdbc:mysql://localhost:3306/mydb",
"com.mysql.jdbc.Driver","root","alunolab");//classe que obtem a conexão
Connection con = conexao.obterConexao();
PreparedStatement comando = con.prepareStatement(sql);
comando.setString(1, nome);
ResultSet resultSet = comando.executeQuery(sql);
livro = new ArrayList<Livro>();
/*recupera os dados no banco de dados,
e os inserem em uma lista, que depois vai ser
retornada quando o método terminar de ser
executado*/
while(resultSet.next())
{
//insere na lista
livro.add(new Livro(resultSet.getInt("isbn"),
resultSet.getString("nome"),
resultSet.getString("autor"),
resultSet.getString("editora"),
resultSet.getString("tarja")));
}[/code]
Pois bem, será que chamando dentro de resultSet (linha 17) executeQuery da classe PreparedStatement é valido? Pois quando tive aula de conexão com o banco de dados, meu professor fez de um jeito um pouquinho diferente, pelo menos em relação a obtenção dos dados, invés de PreparedStatement ele usou Statement.
Além disso, qual é a diferença de PreparedStatement e Statement? Também nas linhas 13 e 17 qual seria a diferença se eles não tivessem argumentos?
O PreparedStatement é capaz de pré-compilar aquela query, antes de envia-la ao banco. Isso quer dizer que, se você executar a query várias vezes seguidas, apenas alterando o valor dos parâmetros, a execução tende a ser mais rápida do que com um Statement.
Além disso, como o PreparedStatement conhece os tipos de cada argumento, ele já faz automaticamente conversões de tipo e trata automaticamente caracteres especiais. Por exemplo, no caso do Statement, o que ocorreria se seu usuário inserisse um nome como The Belgariad’s Son? Pense no que o ’ faria com a query.
Pior que isso, é um ataque chamado de “SQL Injection”. Imagine se um programador tentasse inserir a seguinte query: ’;DELETE * FROM livro;
Com o PreparedStatement, isso não é problema. Pois o ’ não irá fechar a query, e sim, ser considerado a String '.
Outra coisa. Seu tópico não é sobre java básico, e sim, sobre persistência (JDBC). Vou move-lo de fórum. Procure ler atentamente a descrição dos fóruns antes de postar.
Esqueci de comentar, você vai ver uma grande vantagem nos PreparedStatements ao lidar com datas. Sem ele, vc precisa conhecer a String que o banco de dados usa para entender datas na query, e isso varia de banco para banco. Portanto, sem o PreparedStatement, qualquer query com datas não será portável entre um banco e outro.
Com o PreparedStatement, vc simplesmente usa o tipo Date do Java, e deixa que ele se vire para enviar isso pro banco.
Olha, pensei bastante para responder essa pergunta. E chego a conclusão que nunca.
O Statement tem performance ligeiramente melhor se a query será executada apenas uma vez, para um dado conjunto de dados.
Entretanto, ele só é vantajoso se você confiar em 100% nos dados (se não houver chance de SQL Injection).
Um caso talvez fosse rodar uma SQL, escrita por você, uma única vez no banco de dados. Aí vc teria uma performance marginalmente maior na chamada da query. Mas, se você vai rodar uma vez só, não há porque se preocupar com a performance.
Talvez outra situação seja ao rodar queries geradas pela sua própria aplicação, num processo de cópia da estrutura do banco, onde vc terá dezenas de queries diferentes, sendo executadas uma vez só.
Eu, particularmente, nunca uso o Statement. Nem mesmo nos casos acima. Afinal, é um ganho muito pequeno para sequer valer a pena se esquentar com isso.
E, em aplicações comerciais sérias, você provavelmente não usará JDBC direto e sim Hibernate. E ele é capaz de escolher o melhor dos dois.
Outro motivo para usar PreparedStatement em vez de Statement está no próprio banco de dados. Quando você estrutura a query com os parâmetros de um PreparedStatement, você já instrui o banco que sua consulta é parametrizada.
Quando o banco de dados vê uma consulta parametrizada ele faz um “plano de ataque” único para recuperar aquela informação, que é reutilizado posteriomente, mesmo após o término da máquina Java, ou até mesmo em mais de uma máquina java. Enquanto tiver alguém usando a query parametrizada, o banco de dados não joga o plano fora.
Isto é extremamente importante quando sua query é grande e complexa. Tive um caso em que a consulta ao banco baixou de 24 segundos para 200 milissegundos por conta disso.