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

AN style="FONT-SIZE: 10pt; BACKGROUND: white; COLOR: red; FONT-FAMILY: Verdana; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">

Atenção: por essa edição ser muito antiga não há arquivo PDF para download.Os artigos dessa edição estão disponíveis somente através do formato HTML.

Hibernate e Stored Procedures

Obtendo o Melhor dos Mundos O/R e Procedural

 

Aprenda a integrar eficientemente o famoso framework de persistência ás stored procedures de seu banco de dados

 

Desde a sua versão 3.0, o framework de persistência Hibernate suporta a integração com stored procedures para alguns dos principais bancos de dados (Oracle, DB2, Sybase e SQL Server) e atualmente a versão 3.1.3 também oferece suporte a stored procedures desenvolvidas para MySQL e Apache Derby. Neste artigo vamos discutir como tirar o melhor proveito deste recurso de integração.

 

Remédio ou veneno?

Os principais gerenciadores de bancos de dados oferecem linguagens procedurais para o desenvolvimento de stored procedures (SPs). As SPs são tradicionalmente empregadas em sistemas corporativos por três motivos básicos, detalhados a seguir.

 

Aumento de desempenho

Por se tratarem de rotinas armazenadas no próprio banco de dados as SPs têm acesso imediato aos registros das tabelas e são capazes de manipular um grande volume de informações sem gerar tráfego de rede. Variando entre fabricantes de banco de dados, as linguagens procedurais geralmente oferecem estruturas de controle e poderosos mecanismos de manipulação de cursores que permitem uma programação de baixo nível. Nas mãos de programadores experientes, essas linguagens podem resolver muitos problemas e gargalos de desempenho, que a arquitetura cliente/servidor, baseada em instruções SQL, não é capaz de

resolver. É verdade que muitos "gargalos" de desempenho são causados por problemas de modelagem do banco de dados.

Porém, o esforço de construção de uma stored procedure de alto desempenho pode ser menor do que e o necessário para remodelagem e migração de dados de produção.

 

Centralização de regras

Uma segunda motivação para o uso de stored procedures é a possibilidade de centralizar regras de negócio no repositório de dados. Freqüentemente encontramos várias aplicações desenvolvidas em plataformas diferentes acessando o mesmo banco de dados. Nesta situação

pode ser desastroso pressupor que todas as aplicações reproduzem fielmente as mesmas regras de negócio para manipular os dados. Aqui as stored procedures são valiosas para criar uma camada de regras unificada e obrigatória para todos que pretendem operar com os dados. (Triggers de banco de dados podem ser uma opção às SPs neste caso - confira o quadro

"Regras de negócio com Triggers".)

 

Mais segurança

As políticas de segurança de uma empresa podem apontar tabelas que contêm informações sensíveis e que não devem ficar à disposição dos programadores e da maioria das aplicações. As views de bancos de dados constituem uma primeira solução, expondo informações de maneira controlada e reduzindo assim os riscos de segurança.

Porém, em algumas situações o uso de views pode reduzir o desempenho em operações de consultas mais elaboradas especialmente quando precisam ser combinadas com outras tabelas através de joins. Quando encontramos tal impasse podemos abandonar as views e resolver as operações de consulta através de stores procedures desenvolvidas por administradores

de banco de dados (DBAs) ou por outros técnicos com permissão de acesso as tabelas mais sensíveis.

 

Desvantagens

Ao considerar as SPs, não podemos ignorar seus pontos negativos. O primeiro deles é a portabilidade. A criação de muitas stored procedures pode manter as soluções tecnológicas de uma empresa vinculadas a um fabricante de banco de dados, pois as linguagens procedurais

normalmente são proprietárias. Diante da necessidade de adotar um novo gerenciador de banco de dados (SGBD), a tarefa de re-escrita das SPs representa um investimento alto. Num momento como esse, as empresas podem preferir adotar outras arquiteturas para não cair em um novo cenário de dependência de um SGBD específico.

Um outro ponto negativo tem a ver com o desempenho. Uma stored procedure mal programada ou mal testada pode comprometer o desempenho de todo o banco de dados, e conseqüentemente, de todas as aplicações dependentes deste banco.

Discutimos algumas alternativas as SPs no quadro "Alternativas Java".

 

Vantagens do Hibernate no contexto

antes de mostrar como acessar SPs através do Hibernate, vamos comentar quatro capacidades muito importantes do Hibernate, que não podemos perder de vista ao adotar esse framework como solução de persistência.

A primeira dessas capacidades é o que todos esperam em um framework de persistência: o mapeamento objeto-relacional. Uma vez que as colunas das tabelas estejam mapeadas para os atributos das classes, não precisamos escrever instruções em SQL, ou manipular a API JDBC. Mais ainda, não precisamos instanciar e preencher os objetos com valores recuperados

de consultas ao banco de dados.

A segunda capacidade é a portabilidade, que é derivada da primeira. Estando tudo mapeado, podemos migrar nossa aplicação para qualquer outro banco de dados suportado pelo Hibernate. O esforço de migração muitas vezes limita-se a ajustar o dialeto do Hibernate utilizado e, se necessário, modificar nomes de colunas e tabelas nos arquivos (ou anotações) de mapeamento.

A terceira capacidade é menos evidente, mas é extremamente importante para nossa discussão: caches. Através do mapeamento objeto-relacional, o Hibernate compreende como são nossos objetos e como eles se relacionam e levando em conta esse conhecimento, cria caches de objetos em memoria para reaproveitar informações acessadas recentemente,

minimizando consultas ao banco de dados. Veja mais no quadro "Caches do Hibernate".

A quarta capacidade é o mecanismo conhecido como "automatic dirty checking", que percebe as alterações nos objetos vinculados a um cache de sessão e agenda operações de insert, update e delete. Quando executamos o método flush() em um objeto Session do Hibernate, ou quando encerramos uma transação, as operações de modificação "agendadas" são executadas para atualizar o banco de dados com a situação dos objetos em memória.

Mantendo em mente a terceira e a quarta capacidades, conseguiremos integrar corretamente

as SPs ao Hibernate.

 

Hibernate e procedures de persistência

As operações de persistência de objetos via Hibernate acabam gerando operações tradicionais com SQL no banco de dados: select, insert, update e delete. Vamos nos basear em um cenário onde as stored procedures são desenvolvidas para substituir as operações tradicionais, a fim de realizar operações de persistência diferenciadas, em um sistema de cadastro de correntistas

de uma instituição bancária. Os exemplos utilizam a linguagem procedural PL/SQL para bancos de dados Oracle.

A Figura 1 mostra as tabelas de correntistas e funcionários da instituição. Vamos suportar uma regra de negócio que afeta as operações de persistência: "Todo funcionário é considerado um correntista que possui uma conta para recebimento de salário".

No modelo apresentado, a tabela de funcionários pertence ao sistema de recursos humanos, e o acesso direto as colunas ID_FUNCIONARIO, RAMAL e SALARIO não está liberado para o sistema de cadastro de correntistas. Uma tabela auxiliar (tb_funcionarios_aux) armazena informações adicionais do funcionário, que são relevantes para o cadastro de correntistas, inclusive um identificador. Toda vez que dados de correntistas estiverem sob recuperação ou alteração, devemos considerar a tabela tb_correntistas e também as tabelas tb_funcionarios e tb_funcionarios_aux.

Por questões de segurança de dados, uma inserção ou deleção feita através do cadastro de correntistas nunca afeta as tabelas de funcionários (um funcionário é inserido e deletado pelo sistema de RH).

Apresentamos na Listagem 1 as procedures de consulta (get_correntista_id e get_correntistas) capazes de unificar os funcionários aos correntistas. Nessa listagem temos também uma procedure (altera_correntista) para modificar os dados de um correntista, em tb_correntistas ou nas tabelas tb_funcionarios e tb_funcionarios_aux.

Outras abordagens (como herança) poderiam resolver este problema, evitando o uso de stored procedures, mas estamos imaginando uma base de dados legada que possui estas procedures e este modelo de dados homologados.

 

A Listagem 2 mostra a classe dos correntistas e a Listagem 3 apresenta o arquivo de mapeamento objeto-relacional, incluindo o mapeamento das stored procedures.

 

Figura 1. Tabelas do banco de dados

 

Listagem 1. Stored Procedures para Orade (em PL/SQL)                                              

 

create or replace package pkg_correntista as

    type cursor_type is ref cursor;

    function get_correntista_id (

         id IN numeric) return cursor_type;

    function get_correntistas (

         pAgencia IN numeric. pNome IN varchar2)

                    return cursor_type;

    function altera_correntista (

         pAgencia IN integer, pNome IN varchar2,

                   pRg IN varchar2, pCpf IN varchar2,

                   pTelefone IN varchar2,pRef_com IN varchar2,

                   pTel_ref_com IN varcharZ2 pId IN integer) return integer;

end pkg_correntista;

...

Quer ler esse conteúdo completo? Tenha acesso completo