JDBC de Ponta a Ponta - Metadados, transações, segurança e otimização

Nesta parte serão apresentados recursos mais avançados, porém essenciais na maioria das aplicações reais – os metadados de consultas e do próprio banco de dados, o tratamento de erros, o gerenciamento de transações e o uso de comandos preparados.

Esta é a última parte de uma série que visa apresentar o essencial que qualquer programador Java necessita saber para desenvolver aplicações corretas, performáticas e seguras usando JDBC. A primeira parte foi focada mais no desenvolvedor iniciante, apresentando como estabelecer conexões a um banco de dados relacional, o papel do driver JDBC (e como escolher o melhor driver para um dado banco de dados) e como executar comandos SQL de consulta e atualização de dados. Nesta parte serão apresentados recursos mais avançados, porém essenciais na maioria das aplicações reais – os metadados de consultas e do próprio banco de dados, o tratamento de erros, o gerenciamento de transações e o uso de comandos preparados (PreparedStatements).

Os exemplos, tanto da parte inicial quando desta, são desenvolvidos utilizando o banco de dados HSQLDB (veja referências), que é um banco de dados leve e 100% Java. Esta foi uma opção didática, para que o leitor não tivesse como pré-requisito para acompanhar o artigo instalar e configurar um servidor de banco de dados mais “parrudo”. Entretanto todos os exemplos devem funcionar em qualquer outro banco de dados, desde que o driver JDBC correto seja configurado no classpath do sistema, e as propriedades de conexão sejam modificadas para indicar o banco desejado. Todos os exemplos das duas partes foram testados com vários outros bancos, mas não seria possível detalhar aqui os detalhes de configuração para cada possibilidade. O quadro “O exemplo em vários bancos” apresenta os procedimentos para rodar os exemplos deste artigo nos dois bancos livres mais populares, MySQL e PostgreSQL.

Para seguir este artigo é recomendado ter lido a primeira parte, ou pelo menos baixar e estudar o seu código de exemplo. Estamos utilizando a mesma base de dados de exemplo da primeira parte, portanto não serão repetidas aqui as instruções sobre como criar esta base e inserir dados. Mas os fontes para download fornecem os scripts SQL necessários, de modo que leitores com algum conhecimento prévio de SQL e bancos de dados relacionais não terão dificuldades na criação do ambiente para a execução dos exemplos.

Informações sobre o resultado de uma consulta

Existem situações onde é necessário gerar consultas dinamicamente, não sendo possível antecipar quantas colunas farão parte de um resultado (ResultSet) [1], ou qual o tipo de dados de cada coluna retornada. Para situações como essa, o JDBC fornece o método getMetaData() da interface ResultSet. Este método retorna um objeto que implementa a interface ResultSetMetaData. Esta interface, por sua vez, descreve todas as características de cada coluna do resultado e é graças a ela que programas como o Database Manager do HSQLDB ou o SQL Explorer para o Eclipse (veja referências) conseguem executar um comando SQL qualquer e exibir seus resultados de forma organizada.

A Listagem 1 apresenta um exemplo de uso dos metadados do resultado. É um programa que lê um único registro de uma tabela qualquer, desde que seja fornecido o nome da tabela e o valor da chave primária do registro desejado. Neste exemplo consideramos que a chave primária é formada por uma única coluna chamada “id”. Mas o JDBC permitiria uma versão mais sofisticada do exemplo, que consulta o banco de dados para saber quais as colunas que formam a chave primária da tabela requisitada.

import java.sql.*; import java.util.*; public class ListaRegistro { public static void main(String[] args) throws Exception { //... mesmo código dos exemplos da parte 1 para conectar ao banco Statement comando = conexao.createStatement(); String tabela = args[0]; String id = args[1]; ResultSet resultado = comando.executeQuery( "select * from " + tabela + " where id = " + id); if (resultado.next()) { ResultSetMetaData metaDados = resultado.getMetaData(); for (int i = 1; i <= metaDados.getColumnCount(); i++) { System.out.println(metaDados.getColumnName(i) + ": " + resultado.getString(i)); } } else { System.out.println("Não foi encontrado nenhum registro com o id" + id + "."); } //... fecha o resultado, comando e conexão } }
Listagem 1. ListaRegistro.java, exemplo que lista um único registro de uma tabela qualquer, dado o seu id

Não é preciso fechar os objetos de metadados do JDBC, como o ResultSetMetaData. Mas é preciso fechar os resultados retornados por ele.

Com as informações passadas, o programa monta um comando SQL select e então obtém a descrição do resultado, para saber quantas colunas foram retornadas e quais os seus nomes. Eis um exemplo de execução deste programa:

array0 nbsp;javaListaRegistroproduto4 ID:4 NOME:Travesseiroanti-alérgico PRECO:49.00 CATEGORIA:CamaeBanho

A maioria dos desenvolvedores estaria interessada em uma informação mais básica: a quantidade de linhas retornadas por uma consulta. Mas o JDBC não oferece um método que retorne esta informação. O fato é que a maioria dos bancos de dados não “sabe” a quantidade de linhas em um resultado até que este resultado seja inteiramente percorrido. Entre outros motivos, este comportamento permite aos bancos de dados responderem mais rapidamente, consumindo menos memória e reduzindo o tráfego de rede." [...] continue lendo...

Artigos relacionados