Por Paulo Silveira
Aprenda a usar o PreparedStatement para retirar todo código SQL do seu código java, e separá-lo em um arquivo de configuração. Além de uma boa prática, você não precisará mais recompilar o seu código quando necessário mudar pouca coisa de uma SQL.
Introdução
Uma das boas práticas de programação, não só em java, é diminuir ao máximo o uso de Strings literais no seu código fonte, técnica conhecida como "hardcoding". Um "antipadrão" de programação.
Porque isto é ruim? Bem, primeiro que você fica dependendo de recompilar o código se precisar mudar alguma coisa. Segundo que fica difícil você achar um mispelling (erro na hora de digitar) de uma String literal, e terceiro que é terrível ler Strings e magic numbers no código de uma pessoa.
O que é Magic Number?
1 if (this.codigo == 47) { |
O número 47 não representa nada para ninguém, e esse código fica difícil de ser lido. Imagine agora com uma constante:
1 if (this.codigo == DATABASE_ACCESS_ERROR) { |
O mesmo acontece para Strings literais. Claro que em java você utilizaria Exceptions ao invés de código de erros, isto foi apenas um exemplo.
Neste tutorial, aprenderemos a tirar as strings SQLs "hardcodadas" no seu .java, de maneira elegante e eficiente. Para isto, é necessário você ter um conhecimento básico de JDBC e conhecer ajava.util.Properties (ou leia a API!).
Uma vantagem enorme de retirar o seu SQL do .java, é que assim você torna a sua aplicação quase que indepedente de banco de dados (se você tomar bastante cuidado, vira 100% independente). Voce pode mudar em um arquivo de configuracao as SQLs, por exemplo, de TOP para LIMITm diferença clássica entre alguns banco de dados!
java.sql.PreparedStatement é uma interface que extende a interface Statement. A grande maioria dos drivers JDBCs atuais suportam a utilização desta interface. O que ela faz? Bem, vamos dar um exemplo concreto, para irmos explicando:
1 Connection conn = DriverManager.getConnection("jdbc:banco..."); |
Este é o exemplo que está na própria API. O que ele faz? Primeiro ele pega uma conexão com o banco de dados, exatamente como sempre fizemos.
Depois, ele devolve um PreparedStatement a partir de um SQL meio estranho: ele possui pontos de interrogação onde queremos reutilizar a SQL query. Para substituir esses pontos de interrogação, basta usar um dos vários métodos setters que a interface PreparedStatement lhe oferece. Lembre-se que o setter recebe um inteiro, indicando qual ponto de interrogação será utilizado: o primeiro vale 1, diferente de indices de arrays que começam com 0 em java.
Chamado o setter, o driver JDBC vai dar um jeito de traduzir aquele objeto/valor primitivo para dentro da SQL. Se você colocar uma String, não precisa por as aspas!!! Porque? Pois o driver JDBC cuida disso:
1 PreparedStatement pstmt = con.prepareStatement("select * from usuario where name = ?"); |
Uma maneira muito comum de utilizar o PreparedStatement, é usar o método setObject. Este método vai fazer vários instanceof e descobrir como deve colocar esse valor na sua SQL. Caso ele não descubra, ele vai chamar o toString deste método. Continuando o primeiro caso:
1 pstmt.setObject(1, new Long(5000)); |
Se você tentar setar um índice que não exista vai receber uma RuntimeException. Por exemplo, no nosso caso, setObject(3,...) iria resultar em uma RuntimeException, indicando que não existe o 3o ponto de interrogação na SQL dada!
Para executar o PreparedStatement, é idêntnico ao Statement. Lembre-se de "setar" tudo antes de executá-lo, ou você receberá uma exceção:
1 ResultSet rs = pstmt.executeQuery(); // sem passar argumento! |
O que mais o PreparedStatement é responsável por fazer?
Antes que alguém pergunte, o driver de JDBC para o mysql tem sim, suporte a PreparedStatement. Aliás, o GUJ usa e abusa deste recurso, inclusive para guardar as imagens no banco de dados em BLOBs. Aqui você já tem uma idéia legal de como aproveitar o PreparedStatement, mas sugiro que você conheça a api dele,clicando aqui. Após aprendermos a usar o PreparedStatement, vamos fazer algo para retira-los do seu .java. Para isso, vamos passar todas as Strings que representam uma SQL para um arquivo de Properties, algo do tipo:
Então, ao invés de criarmos o PreparedStatement a partir de um String literal, nós pegamos ele a partir deste arquivo Properties. Um esboço:
Na hora de criar um PreparedStatement, você faz assim:
Onde USUARIO_SELECT_BY_NAME é uma constante: uma String static final e pública. Porque isso? evitar o hardcoding e erros de execução. Com isso, você não terá mais nenhum SQL dentro do seu .java, o que é um grande passo. Vamos melhorar nosso esboço de como controlar essa properties que contém os SQLs. Vamos criar aqui uma classe (esboço novamente) para controlar essa properties que tem as SQLs. Não podemos ficar lendo do arquivo texto toda vez que pegarmos uma SQL, precisamos de uma classe (instância dela) para fazer isso. Você não precisa saber o que é um Singleton. É basicamente uma solução para você não fazer uma classe que tenha tudo static, desta maneira, você perderia a orientação a objetos.
Até aqui temos o padrão singleton implementado, mas vamos adicionar o método que retorna um PreparedStatement, dado uma conexão e o nome do statement que você quer!
Cuidado: este método pode dar NullPointerException no caso da query requerida não existir no arquivo de configuração! Para utilizar esta classe:
Simples não? Não tenha medo do singleton, a única coisa que ele faz é impedir que exista mais de uma instância desta classe por ClassLoader. Este tutorial foi realizado devido a muitos pedidos de como retirar o SQL do codigo java. Você pode refinar o processo, utilizando XML no caso que você tenha uma hierarquia entre as SQLs. O problema seria escrever um parser apenas para este arquivo de configurações. Você ainda pode melhorar essa solução: utilizando alguma biblioteca/ferramenta que possibilite o "mapeamento objeto relacional". Usar uma ConnectioPool também é muito útil! Espero que tenha ficado claro a melhoria que você ganha a partir do momento que para de lidar com literais: maior reuso do código, melhor leitura, maior adaptação e facilidade de reescrita. E é claro: quem não gosta de um arquivinho de configurações :). |
Fonte : http://www.guj.com.br/java.tutorial.artigo.115.1.guj
Nenhum comentário:
Postar um comentário
Comentários sobre assuntos não relacionados ao objetivo deste blog serão removidos.