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

Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Confirmar voto
0
 (0)  (0)

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.

Esse artigo faz parte da revista Java Magazine edição 42. Clique aqui para ler todos os artigos desta edição

JDBC de Ponta a Ponta

Parte 2: Metadados, transações, segurança e otimização

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.

 

Listagem 1. ListaRegistro.java, exemplo que lista um único registro de uma tabela qualquer, dado o seu id

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

  }

}

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:

 

$ java ListaRegistro produto 4

ID: 4

NOME: Travesseiro anti-alérgico

PRECO: 49.00

CATEGORIA: Cama e Banho

 

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.

Então, caso sua aplicação precise indicar a quantidade de registros que retornaram em uma consulta, há duas alternativas: a aplicação deve contar os registros à medida que percorre o resultado, e percorrer todas as linhas do resultado; ou então executar um comando SQL select count(*).

Tratamento de erros de banco

Até este ponto, nenhum dos programas de exemplo realizou qualquer tipo de tratamento de erros. Como é usual em exemplos iniciais, estamos operando em um mundo ideal onde tudo funciona perfeitamente. Mas no mundo real, é claro, muitas coisas podem sair erradas. A rede pode estar com problemas, o servidor de banco de dados pode ter ficado sem espaço em disco, ou o programador pode ter errado a sintaxe de um comando SQL ou digitado incorretamente o nome de uma tabela ou campo.

Lembre que os comandos SQL são apenas strings dentro do código Java, portanto erros só serão reportados durante a execução da aplicação.

Muitas APIs do Java geram exceções onde o tipo (classe) da exceção já indica que tipo de erro ocorreu. Mas o JDBC irá gerar apenas a exceção “genérica” SQLException[2].  "

A exibição deste artigo foi interrompida :(
Este post está disponível para assinantes MVP

 
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Receba nossas novidades
Ficou com alguma dúvida?