Artigo Java Magazine 45 - Stored Procedures com Java

Aprenda a chamar stored procedures de bancos de dados relacionais em JDBC de modo eficiente e independente do banco de dados, conheça seqüências de escape JDBC, e saiba quando usar ou não procedures nas suas aplicações.

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

Clique aqui para ler esse artigo em PDF.

Stored Procedures com Java

Como chamar stored procedures via JDBC

Aprenda a chamar stored procedures de bancos de dados relacionais em JDBC de modo eficiente e independente do banco de dados, conheça seqüências de escape JDBC, e saiba quando usar ou não procedures nas suas aplicações

Todo desenvolvedor Java que atue na área de Sistemas de Informação irá, mais cedo ou mais tarde, se deparar com a necessidade do uso de stored procedures, que são procedimentos armazenados e executados dentro do próprio bancos de dados. Embora haja um debate exaltado na comunidade sobre a relevância deste recurso dentro do Java EE ou com frameworks de persistência de objetos (veja o quadro “Quando usar (ou não) stored procedures com Java”), estamos longe de chegar ao ponto de se considerar as stored procedures como apenas mais uma tecnologia legada.

Há uma variação enorme de sintaxe e recursos disponíveis nas linguagens de programação embutidas em cada banco de dados para a criação de stored procedures, criando dificuldades no porte de aplicações de um banco de dados para outro. Mas felizmente o lado Java é padronizado, graças à API JDBC.

Este artigo foca o lado Java da questão, utilizando exemplos escritos para os dois bancos de dados livres mais populares, o MySQL e o PostgreSQL. Espera-se do leitor um conhecimento de básico para intermediário na instalação e configuração destes bancos. Os fontes para download fornecem scripts SQL prontos para a criação das bases de dados, tabelas e stored procedures de exemplo, que são descritos no quadro “Stored procedures no MySQL e no PostgreSQL”. Também espera-se conhecimento de básico para intermediário da API JDBC, preferencialmente que inclua o uso da interface PreparedStatement. Os dois artigos da série “JDBC de Ponta a Ponta”, publicados nas Edições 41 e 42 tratam deste e de vários outros assuntos relacionados.

Os programas de exemplo Java usam um banco de dados com sumários da venda de produtos por região geográfica, contendo duas tabelas relacionadas: produto e vendas. Os scripts de inicialização do banco de dados, disponíveis para download no site da Java Magazine, já criam estas tabelas, inserem uma massa de dados para testes, e definem as stored procedures que são chamadas pelas aplicações Java.

Se as definições das tabelas são idênticas para os dois bancos, a programação das stored procedures é radicalmente diferente em cada caso, e terá que ser completamente reescrita para rodar os mesmos exemplos em outros bancos como Firebird, Derby ou Oracle. Por isso não iremos entrar em detalhes sobre o código no banco de dados. No entanto, apresentaremos o essencial necessário para o leitor entender o funcionamento das stored procedures e seus parâmetros e o que funciona ou não nos dois BDs de exemplo.

A primeira stored procedure

Um cenário muito comum é chamar uma stored procedure que realiza várias alterações no banco de dados, mas que não retorna nenhuma informação para a aplicação Java. Caso haja algum erro durante a execução da stored procedure, será gerada uma SQLException. Senão considera-se que tudo transcorreu bem.

Para exercitar este cenário, nosso primeiro exemplo chama uma stored procedure, chamada incrementa, que aumenta a quantidade de produtos vendidos dado o produto e a região. A Listagem 1 apresenta o código Java deste exemplo. A listagem apresenta a declaração das procedures no MySQL e PostgreSQL (nessa ordem) de modo a indicar os parâmetros e valores de retorno; o código Java que faz a chamada; e um exemplo de execução da aplicação Java no prompt de comandos do sistema operacional.

 

Listagem 1. Incrementa.java – incrementa o campo valor da tabela contador

-- soma <quantidade> à quantidade de unidades vendidas do produto identificado

-- por <nome_produto> na região identificada por <sigla_regiao>

 

-- MySQL:

create procedure incrementa (nome_produto varchar(30), sigla_regiao char(2),

    quantidade integer)

 

-- PostgreSQL:

create function incrementa (nome_produto varchar(30), sigla_regiao char(2),

    quantidade integer) returns void

 

Incrementa.java

import java.sql.*;

import java.util.*;

 

public class Incrementa

{

  public static void main(String args[]) throws Exception {

    // valida a linha de comando

    if (args.length != 3) {

      System.err.println("Uso: Incrementa <produto> <regiao> <quantidade>");

      System.exit(-1);

    }

 

     // obtém parâmetros de conexão via arquivo de propriedades

    Properties parametrosConexao = new Properties();

    parametrosConexao.load(Incrementa.class.getResourceAsStream(

      "banco.properties"));

    String driver = parametrosConexao.getProperty("driver");

    String url = parametrosConexao.getProperty("url");

    String login = parametrosConexao.getProperty("login");

    String senha = parametrosConexao.getProperty("senha");

 

     // conecta ao banco e chama a stored procedure   

    Class.forName(driver);

    Connection con = DriverManager.getConnection(

      url, login, senha);

     CallableStatement stmt = con.prepareCall(

       "{call incrementa(?, ?, ?)}");

    stmt.setString(1, args[0]);

     stmt.setString(2, args[1]);

     stmt.setInt(3, Integer.parseInt(args[2]));

     stmt.execute();

 

  // se não houve exceção tudo funcionou ok.

  System.out.println("Registrado aumento de vendas do produto.");

 

  // libera recursos

  stmt.close();

  con.close();

   }

}

 

Execução do exemplo usando o MySQL

 

$ mysql -h 127.0.0.1 -u usuario -p sproc

...

mysql> select produto.nome, vendas.regiao, vendas.qtde from vendas, produto

    -> where vendas.produto = produto.id;

+--------------------------+--------+------+

| nome                     | regiao | qtde |

+--------------------------+--------+------+

| iPod Nano                | RJ     |  322 |

| iPod Nano                | SP     |  518 |

| Edredon dupla face       | RJ     |  567 |

...

8 rows in set (0.00 sec)

 

mysql> \q

 

$ java Incrementa "iPod Nano" RJ 15

Registrado aumento de vendas do produto.

" [...] continue lendo...

Artigos relacionados