Início > Programação > Mapeamento de Stored Procedures do Oracle em Java

Mapeamento de Stored Procedures do Oracle em Java

Uma procedure é um conjunto de declarações PL/SQL que pode ser chamada por um nome e pode aceitar argumentos (parâmetros). Como uma procedure é armazenada como um schema no banco de dados, o código pode ser reutilizado. Essas características tornam uma procedure mais eficiente que um bloco anônimo.

Como adiantei nesse artigo, procedures podem retornar valor. Vamos fazer uma procedure que, dado o identificador de uma pessoa, retorna o próprio identificador, a idade e o nome.

1. Crie uma tabela para armazenar os dados das pessoas:

CREATE TABLE TBL_PESSOA
(
  PK     NUMBER(3) NOT NULL,
  NOME   VARCHAR2(64) NOT NULL,
  IDADE  NUMBER(2) NOT NULL
);

2. Vamos inserir um registro para poder validar a procedure:

INSERT INTO TBL_PESSOA
VALUES (1,'JOSÉ', 30);

3. Defina a procedure. Note que a implementação da nossa procedure tem apenas um select simples restrito ao parâmetro de entrada e faz a atribuição de valores aos parâmetros de saída:

CREATE OR REPLACE PROCEDURE PROCEDURE_BUSCAR_USUARIO
  (P_IN_ID IN NUMBER, P_ID OUT NUMBER, 
   P_IDADE OUT NUMBER, P_NOME OUT VARCHAR2)
IS
PK NUMBER;
NOME VARCHAR2(64);
IDADE NUMBER;
BEGIN
   SELECT TP.PK, TP.NOME, TP.IDADE
   INTO PK, NOME, IDADE
   FROM TBL_PESSOA TP
   WHERE TP.PK = P_IN_ID;
   P_ID := PK;
   P_NOME := NOME;
   P_IDADE := IDADE;
END PROCEDURE_BUSCAR_USUARIO;

4. Vamos definir a classe Pessoa. Como não estamos trabalhando com ORM, não é necessário anotações da JPA. Basta um POJO:

public class Pessoa {
   private Integer id;
   private String nome;
   private Integer idade;
   // getters e setters
   public Pessoa(Integer id, Integer idade, String nome) {
      this.id = id;
      this.idade = idade;
      this.nome = nome;
   }
}

5. Vamos utilizar a interface Work do Hibernate para ter acesso à Connection:

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
import org.hibernate.Session;
import org.hibernate.jdbc.Work;

public class Procedure {
   private Pessoa pessoa;
   private Session session;
   public Procedure(Session session) {
      this.session = session;
   }
   public Pessoa getPessoa() {
      return pessoa;
   }
   public void execute(final Integer idPessoa) {
      session.doWork(new Work() {
         @Override
         public void execute(Connection con) throws SQLException {
            CallableStatement callStm = null;
            try {
               callStm = con.prepareCall(
                "{call PROCEDURE_BUSCAR_USUARIO(?, ?, ?, ?)}");
               registrarParametroEntrada(callStm, "P_IN_ID", idPessoa);
               registrarParametroSaida(callStm, "P_ID", Types.INTEGER);
               registrarParametroSaida(callStm, "P_IDADE", Types.INTEGER);
               registrarParametroSaida(callStm, "P_NOME", Types.VARCHAR);
               callStm.execute();
               Integer id = extrairInteger(callStm, "P_ID");
               Integer idade = extrairInteger(callStm, "P_IDADE");
               String nome = extrairString(callStm, "P_NOME");
               pessoa = new Pessoa(id, idade, nome);
            } finally {
               if (callStm != null) {
                  callStm.close();
               }
            }
         }
      });
   }

   private <T extends Object> T extrair(CallableStatement cs,  
        String nomeParametro, Class<T> clazz)
      throws SQLException {
      Object object = cs.getObject(nomeParametro);
      if (object == null) {
         return null;
      }
      return clazz.cast(object);
   }
   
   private String extrairString(CallableStatement cs, 
        String nomeParametro) throws SQLException {
      return extrair(cs, nomeParametro, String.class);
   }

   private Integer extrairInteger(CallableStatement cs, 
        String nomeParametro) throws SQLException {
      return extrair(cs, nomeParametro, Integer.class);
   }

   private void registrarParametroEntrada(CallableStatement cs, 
        String nomeParametro, Integer valor)
      throws SQLException {
      cs.setObject(nomeParametro, valor, Types.INTEGER);
   }

    private void registrarParametroSaida(CallableStatement cs, 
      String nomeParametro, int sqlType) throws SQLException {
      cs.registerOutParameter(nomeParametro, sqlType);
   }
}

6. Por fim, crie um método no seu DAO para acessar a procedure:

@Stateless
public class PessoaDao
{
   @PersistenceContext(unitName = "pu")
   private EntityManager em;

   private Session getSession(){
      return (Session) em.getDelegate();
   }

   public Pessoa buscar(final Integer idPessoa) {
      Procedure procedure = new Procedure(getSession());
      procedure.execute(idPessoa);
      return procedure.getPessoa();
   }
}

Referências

1. [https://docs.oracle.com/cd/B28359_01/appdev.111/b28843/tdddg_procedures.htm]
2. [https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_5009.htm]
3. [https://justonedeveloper.wordpress.com/2013/05/29/convert-hibernate-session-to-jdbc-connection/]

Anúncios
  1. Nenhum comentário ainda.
  1. 10/10/2016 às 7:37 AM

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: