Acelere aplicativos de Hibernate e iBATIS usando o pureQuery, Parte 1: Usando o IBM Integration Module para Hibernate e pureQuery

Habilite SQL Estática e Lotes Heterogêneos Usando um Novo Módulo de Integração

Quando é estendido com o IBM® Integration Module, que pode ser obtido por download, o IBM Optim® pureQuery Runtime simplifica o processo de gerar SQL estática de DB2 para aplicativos de Hibernate e iBATIS. O programa faz isso sem necessidade de alterações no código do aplicativo e de reunir a SQL das cargas de trabalho de produção. O Optim pureQuery Runtime também permite que os aplicativos de Hibernate e iBATIS que acessam o DB2 ou o Informix ® aproveitem o recurso de lotes heterogêneos em pureQuery. Com o recurso de lotes heterogêneos, é possível formar lotes de várias solicitações de INSERT, UPDATEe DELETE antes de enviá-las pela rede, inclusive quando as solicitações fazem referência a várias tabelas. Este artigo é o primeiro de uma série com duas partes. Descreve o uso do IBM Integration Module com aplicativos de Hibernate. A Parte 2 focará os aplicativos de iBATIS. Este artigo inclui um exemplo de aplicativo que pode ser obtido por download e ilustra como é possível habilitar facilmente esses dois recursos. O artigo também fornece medições informais de tempo decorrido e desempenho.

Kathy Zeidenstein, Senior Software Engineer, IBM

Author Photo: Kathy ZeidensteinKathy Zeidenstein trabalha na IBM há muitos anos. Vem atuando em desenvolvimento de informações, gerenciamento de produtos e marketing de produtos. Atualmente, é a gerente responsável pelo desenvolvimento de informações para soluções Optim voltadas ao desenvolvimento, administração e design de banco de dados. Anteriormente, trabalhou na equipe de habilitação técnica de soluções de IBM Optim e foi responsável pelo desenvolvimento de comunidade e comunicações.



Mario Briggs, Senior Software Engineer , IBM

Mario  Briggs photoMario Briggs é líder das ofertas de Open Source para IBM DB2 e IBM Informix, incluindo PHP, Ruby/Rails, Python/Django/SqlAlchemy, Perl e estruturas de acesso a dados Java. Mario tem aproximadamente 11 anos de experiência em desenvolvimento de software e passou vários desses anos nas áreas de acesso a dados, mecanismos relacionais e desempenho de bancos de dados de aplicativos.



Abhigyan Agrawal, Software Engineer, IBM

Abhigyan Agrawal photoAbhigyan Agrawal é engenheiro de software e faz parte da equipe de Open Source nos Laboratórios de Software da IBM Índia. Atualmente, está realizando um trabalho para fornecer suporte à SQL estática de DB2 para Hibernate. Anteriormente, realizou um trabalho para fornecer suporte à SQL estática de DB2 em iBATIS e desenvolveu os drivers do IBM Python. Adquiriu o título de Mestre em Engenharia em Tecnologia da Informação pelo IIIT, em Bangalore.



Sandhya Turaga, Software Engineer, IBM

Sandhya Turaga photoSandhya Turaga é engenheira de software e faz parte da equipe de desenvolvimento de consulta de objetos no Laboratório IBM em Silicon Valley. Anteriormente, quando era estagiária na IBM, ela trabalhou na melhoria do desempenho de consultas para a linguagem de consulta de objetos do ObjectGrid. Adquiriu o título de mestre em Ciências da Computação pela San Jose State University em maio de 2008, com uma tese sobre computação em grade.



12/Mai/2014

Visão geral

O pureQuery é uma plataforma de acesso a dados de alto desempenho formada por ferramentas de desenvolvimento, uma® API de Java, um tempo de execução e serviços de monitoramento. Usando a API leve de pureQuery, é possível escrever um código de acesso a dados que acessa DB2, Informix e até mesmo bancos de dados Oracle. No entanto, vários dos benefícios do pureQuery como — a capacidade de visualizar e modificar a SQL gerada, o uso de boas práticas de acesso ao banco de dados, o suporte a recursos de desempenho como lotes heterogêneos e a capacidade de reunir dados de desempenho a partir de consultas — não requerem o uso da API. Para obter mais informações sobre pureQuery, consulte a seção Recursos .

Um caso de uso chave para utilizar o pureQuery com aplicativos já existentes pode ser observado nos servidores de dados de DB2, nos quais é possível converter o modo de execução de SQL da execução dinâmica (padrão para os aplicativos de Java) para a execução estática. Isso elimina a necessidade de preparação no tempo de execução e pode reduzir o risco de injeção de SQL. Para obter mais informações sobre os benefícios da execução estática, consulte a seção Recursos .

Com o pureQuery, também é possível aproveitar os recursos do Optim Development Studio — como visualizar métricas de desempenho e correlacionar as instruções SQL geradas ao código de origem de Java que as originou. Isso torna o pureQuery útil para o uso com aplicativos já existentes que acessam bancos de dados Oracle e Informix. A Figura 1 é uma captura instantânea do Optim Development Studio com alguns recursos chave ressaltados.

Figura 1. Visualização da estrutura de tópicos do Optim Development Studio

Para obter mais informações sobre o Optim Development Studio, consulte a seção Recursos .

Há duas formas de aproveitar o pureQuery com aplicativos já existentes que não foram escritos com a API do pureQuery. É possível usar esses métodos separados ou juntos:

  • Use a otimização de cliente para fazer o Optim pureQuery Runtime capturar SQL (e os metadados associados de desempenho e aplicativos) enquanto o programa de Java está em execução. Essa abordagem é flexível, pois é possível usá-la com qualquer aplicativo de Java, inclusive aplicativos empacotados. Entretanto, requer configuração adicional e a execução de vários caminhos no código para assegurar que toda a SQL seja capturada. Depois que a SQL é capturada, é possível usar toda a capacidade do Optim Development Studio para modificar a SQL, visualizar os caminhos de acesso, fazer testes de desempenho e a análise de impacto. A seção Recursos contém um link para um tutorial que descreve como usar a otimização de cliente.
  • Use módulos de integração para possibilitar que os programas aproveitem toda a capacidade do pureQuery e do Optim Development Studio sem necessidade de uma etapa inicial de captura. Esta é uma nova abordagem e é o foco dessa série de artigos. Com essa abordagem, o Integration Module extrai a SQL e os seus metadados antes da execução do programa de Hibernate/iBATIS. Anteriormente, esse suporte estava disponível para o WebSphere® OpenJPA (consulte a seção Recursos para obter um link para o artigo sobre esse assunto). Agora, com os novos módulos de integração, esse suporte também está disponível para aplicativos de Hibernate e iBATIS. Com esses módulos, é possível usar um conjunto de ferramentas para visualizar e otimizar a SQL sem fazer uma captura de tempo de execução (também é possível usá-la em conjunto com a captura, conforme o descrito em Usando a captura incremental para reunir consultas de Criteria.)

O IBM Integration Module para Hibernate e pureQuery possibilita os seguintes benefícios para os aplicativos de Hibernate:

  • Os aplicativos de Hibernate podem usar SQL estática sem a necessidade da captura inicial de otimização de cliente do pureQuery. O Integration Module gera a SQL que pode ser usada pelo aplicativo de Hibernate. A SQL pode ser vinculada estaticamente para o acesso a bancos de dados de DB2 e pode ser revisada, compartilhada, otimizada e substituída sem alterar o aplicativo em si. A SQL também pode ser correlacionada ao código do aplicativo para rastrear problemas de desempenho até o código de origem do Hibernate ou às alterações de objetos de banco de dados para fazer a análise de impacto usando o Optim Development Studio.
  • Os seus aplicativos de Hibernate podem usar o recurso de lotes heterogêneos no pureQuery. Esse recurso permite formar lotes de várias solicitações de INSERT, UPDATEe DELETE até mesmo quando fazem referência a várias tabelas. Por exemplo: a atualização de um objeto de funcionário que requer a atualização de várias tabelas de banco de dados que constituem o objeto pode ser feita em um único acesso ao banco de dados, e não em vários acessos. Cada roundtrip da rede ao servidor de banco de dados custa caro em termos de desempenho. Portanto, sob o ponto de vista do desempenho, é melhor ter menos roundtrips, mas lotes maiores. Esse suporte está disponível para bancos de dados de DB2 e Informix.

Este artigo descreve como configurar e usar o Integration Module para Hibernate e pureQuery. Primeiro, descreve o recurso de SQL estática do Integration Module e, em seguida, descreve o recurso de lotes heterogêneos. O artigo pressupõe que você tem algum conhecimento sobre o Hibernate e que está usando o Hibernate 3.2 ou posterior. É possível aproveitar os benefícios oferecidos pelo Integration Module sem alterar o código do aplicativo.

O que é SQL estática e como pode ajudar no desempenho?

A SQL estática no DB2 é um recurso poderoso que possibilita otimizar o acesso a dados no tempo de execução. Ela faz isso ao realizar parte do trabalho — como determinar o caminho de acesso ao banco de dados — antecipadamente. Isso ajuda a fazer o tempo de execução funcionar de forma mais rápida e consistente. A Figura 2 mostra uma comparação entre a execução da SQL dinâmica e da SQL estática.

Figura 2. Execução da SQL estática em comparação com a execução da SQL dinâmica

O modelo de segurança para a SQL estática também é diferente do modelo para a SQL dinâmica. Com a SQL estática, os usuários só recebem privilégios para executar a saída do processo de ligação, conhecido como pacote. Esse pacote contém as instruções SQL. Portanto, se todo o acesso a uma tabela é estático, bastaria dar acesso somente ao pacote, e não a toda a tabela ou visualização. Além disso, ao usar SQL estática você reduz a oportunidade de injeção mal intencionadaum risco à segurança bastante conhecido da SQL dinâmica.

Para obter mais informações sobre a SQL estática consulte a seção Recursos .


Visão geral da criação de SQL estática com o Integration Module para Hibernate e pureQuery

Esta seção compara a execução padrão de um aplicativo de Hibernate (SQL dinâmica) com uma execução que usa o Integration Module para criar e usar SQL estática.

Execução de SQL dinâmica pelo Hibernate: JDBC

A Figura 3 mostra a execução geral de um aplicativo de Hibernate sem o Integration Module. O Hibernate gera as cadeias de instrução SQL e as executa no banco de dados usando as operações "prepare" e "execute" de JDBC.

Figura 3. Execução de SQL dinâmica de um aplicativo de Hibernate sem o Integration Module

Execução de SQL estática pelo Hibernate com o Integration Module: pureQuery

A Figura 4 mostra a execução detalhada de um aplicativo do Hibernate com o Integration Module. Os pacotes do DB2 foram criados para a execução de SQL estática. A figura descreve o seguinte:

  • Uma etapa de geração de SQL (HibernateGen) reúne toda a SQL que o aplicativo de Hibernate usa em um arquivo XML de pureQuery (esses arquivos são do tipo .pdqxml). Em seguida, esse arquivo pode ser usado no Optim Development Studio para ajuste ou análise de impacto sem necessidade de uma etapa de BIND . O arquivo XML de captura do pureQuery pode ser ligado a pacotes estáticos com o Static Binder.
  • Durante a execução do aplicativo, o pureQuery Runtime redireciona as chamadas ao JBDC para executar os pacotes estáticos de DB2 que foram criados na etapa de geração. O arquivo pdq.properties controla o comportamento de execução do pureQuery Runtime (dinâmico ou estático) e também fornece a localização do arquivo XML do pureQuery.
Figura 4. Execução de SQL estática de um aplicativo do Hibernate com o Integration Module

Quais instruções SQL podem ser extraídas de um aplicativo do Hibernate?

As seguintes instruções SQL podem ser extraídas pelo Integration Module:

  • SQL para consultas nomeadas — Java Persistence Query Language (JPQL) e Hibernate Query Language (HQL)
  • SQL para consultas nomeadas nativas — consultas nomeadas SQL, Java Persistence API (JPA) e Hibernate API especificados
  • SQL para operações de Create, Read, Update e Delete (CRUD) em Hibernate Beans/entidades — JPA e API nativa
  • SQL para operações de CRUD em coleções em Hibernate Beans/entidades — JPA e API nativa

SQL para consultas de Criteria e consultas lineares não são geradas pelo Integration Module. Deve-se evitar incorporar consultas HQL no código Java a menos que sejam consultas realmente dinâmicas. Nesses casos, não é possível aplicar SQL estática a essas consultas. Para obter informações sobre a externalização de consultas HQL, consulte a seção Recursos .


O que são lotes heterogêneos e como podem ajudar no desempenho?

O Hibernate usa JDBC para o acesso a dados. O JDBC suporta uma forma de lote chamada lotes homogêneos. Essa forma de lote está restrita a tabelas únicas e a várias execuções da mesma instrução SQL, desde que a instrução tenha parâmetros de entrada. No entanto, ao atualizar vários tipos de entidade em uma transação ou usar mapeamento de entidades que envolvem tabelas secundárias, herança de junção ou herança de tabela por classe, uma transação pode conter várias instruções SQL envolvendo várias tabelas. Nesses casos, os lotes de JDBC não são efetivos.

Além disso, o lote de JDBC só suporta a adição de instruções SQL diferentes ao lote, desde que as instruções SQL não tenham parâmetros de entrada. No entanto, os aplicativos típicos que usam Hibernate (ou OpenJPA) usariam instruções SQL com parâmetros de entrada devido à característica dinâmica dos aplicativos. Nesses cenários, os lotes de JDBC não permitem lotes de instruções SQL diferentes.

Considere o cenário de lote mostrado na Lista 1.

Lista 1. Um cenário de lote
PreparedStatement pstmt = conn.prepareStatement("update T1 set name=? where id=?");
pstmt.setString(1,"name1");
pstmt.setInt(2,1);
pstmt.addBatch();

pstmt.setString(2,"name2");
pstmt.setInt(2,2);
pstmt.addBatch();

pstmt.executeBatch();

Não é possível adicionar a instrução SQL delete from T1 where ID = ? ao lote mostrado na Lista 1. Em vez disso, seria necessário criar outra preparedStatement para a exclusão, e outra mensagem seria enviada ao servidor de banco de dados para preparar a instrução para a consulta de exclusão.

Talvez seja possível usar lotes heterogêneos, que estão disponíveis com o pureQuery, para melhorar o desempenho em situações que não estão cobertas pelos lotes de JDBC. Por exemplo: examine novamente o cenário mostrado na Lista1. Com o pureQuery, é possível adicionar as instruções SQL na Lista 2 ao mesmo lote de pureQuery. Em seguida, o pureQuery prepararia a instrução e enviaria todas essas instruções ao servidor de banco de dados em uma única mensagem. Isso pode melhorar o desempenho.

Lista 2. Lotes heterogêneos
update T1 set name=? where id=?
delete from T1 where ID = ?

A Tabela 1 resume algumas características dos programas que podem aproveitar os lotes heterogêneos do pureQuery.

Tabela 1. Cenários onde os lotes heterogêneos do pureQuery podem ser úteis

Característica do programaSuportado pelos lotes heterogêneos do JDBC?Suportado pelos lotes heterogêneos do pureQuery?
Forma lotes das atualizações para entidades que se correlacionam a várias tabelasNãoSim
Forma lotes das atualizações com relação à mesma tabela, mas colunas diferentesNão (a menos que esteja usando literais em vez de parâmetros de entrada)Sim
Forma lotes de várias operações (INSERT, UPDATE, DELETE) com relação à mesma tabelaNão (a menos que esteja usando literais em vez de parâmetros de entrada)Sim
Forma lotes de atualizações com relação a várias entidadesNão (a menos que esteja usando literais em vez de parâmetros de entrada)Sim

Os lotes heterogêneos não fornecem uma melhora no desempenho do aplicativo nos seguintes cenários:

  • O aplicativo é formado somente por instruções SELECT . Isso acontece porque os lotes heterogêneos na release atual do Integration Module só melhoram o desempenho de instruções INSERT, UPDATE e DELETE .
  • O aplicativo usa entidades com identidade de tabela ou geração de chaves de sequência de banco de dados.

Visão geral da habilitação de lotes heterogêneos com o Integration Module

Esta seção compara a execução de um aplicativo de Hibernate que usa os lotes heterogêneos do pureQuery a um aplicativo que não os usa.

Lotes padrão no Hibernate: JDBC

A Figura 5 mostra o fluxo geral de execução do exemplo de aplicativo de Hibernate sem os lotes heterogêneos do pureQuery. (O exemplo de aplicativo está disponível na seção Download .) O Hibernate gera cadeias de instruções INSERT, UPDATE e DELETE e as passa para o perseverador de classe para execução. O perseverador chama o processador de lotes para realizar as operações "prepare" e "execute" de JDBC.

Figura 5. Execução de um aplicativo de Hibernate sem os lotes heterogêneos do pureQuery

Lotes heterogêneos no Hibernate: pureQuery

A Figura 6 mostra o fluxo geral de execução do exemplo de aplicativo do Hibernate com lotes heterogêneos do pureQuery. O Hibernate gera cadeias de instruções INSERT, UPDATE e DELETE e as passa para o perseverador de classe para execução.

O IBM Integration Module implementa o processador de lotes, eventListener e as interfaces do perseverador para possibilitar que as instruções SQL INSERT, UPDATE e DELETE sejam roteadas para o pureQuery e não para o JDBC e aproveitem os lotes do pureQuery. O FlushListener notifica o processador de lotes para executar o lote assim que todas as instruções SQL forem adicionadas ao lote a partir de uma transação. A versão atual do Integration Module não suporta lotes heterogêneos de instruções SELECT , para que não passem pelo perseverador e processador de lotes personalizado.

Figura 6. Execução de um aplicativo Hibernate com lotes heterogêneos de pureQuery

Pré-requisitos para usar o IBM Integration Module para Hibernate e pureQuery

A seção Recursos contém um link que você pode usar para fazer o download do IBM Integration Module para Hibernate e PureQuery.

Software

Para usar o pureQuery Integration Module, é necessário ter:

  • Optim pureQuery Runtime 2.2.0.3 ou superior (Consulte a seção Recursos para ver o link para fazer o download de uma versão de avaliação de 30 dias do IBM Optim Development Studio e do Optim pureQuery Runtime. O tempo de execução deve estar na mesma máquina que o Optim Development Studio.)
  • Certifique-se de que pdq.jar e pdqmgmt.jar estejam no caminho da classe.
  • IBM Data Server Driver para JDBC e SQLJ 3.58 ou 4.7 (disponível com o Optim Development Studio) ou consulte a seção Recursos para ver o link para fazer o download).
  • Hibernate 3.2 ou posterior.

O Integration Module contém um utilitário validador que pode ser usado para verificar os pré-requisitos. Consulte Use o utilitário versionValidator para verificar os pré-requisitos para ver as instruções de uso do utilitário.

Bancos de dados suportados

O IBM Integration Module para Hibernate e pureQuery funciona quando o aplicativo está acessando qualquer um dos seguintes sistemas de banco de dados:

  • DB2 para Linux®, UNIX®e Windows® V8.2, Fix Pack 11 ou posterior
  • DB2 para Linux, UNIX e Windows V9.1, V9.5, ou V9.7
  • DB2 para i V5R4 (somente recurso de lotes heterogêneos)
  • DB2 para z/OS® V8 ou posterior
  • Informix Dynamic Server V11.10 ou V11.5 (somente recurso de lotes heterogêneos)

Exemplo de aplicativo usado neste artigo

O arquivo DemoHibApp.zip na seção Download contém um exemplo de aplicativo que pode ser usado para experimentar o recurso caso você esteja usando o Hibernate 3.2 ou posterior.


Habilitando a SQL estática do pureQuery para aplicativos de Hibernate

Esta seção usa o exemplo de aplicativo de Hibernate para ajudar a explicar como o IBM Integration Module funciona para SQL estática.

Edite Provider em persistence.xml

Se você está usando persistence.xml, para habilitar o suporte a SQL estática do pureQuery, é necessário garantir que a propriedade de provedor esteja especificada em persistence.xml.

No exemplo de aplicativo, essa propriedade já está definida, como mostra a primeira linha da Lista 3.

Lista 3. Propriedade obrigatória em persistence.xml para habilitar a SQL estática do pureQuery
<provider>com.ibm.pdq.hibernate3.PDQHibernatePersistence</provider>
<!-- <provider>org.hibernate.ejb.HibernatePersistence</provider> -->

Se você está usando hibernate.cfg.xml, não é necessário alterá-lo.

Por que a alteração de Provider é obrigatória para possibilitar o uso de SQL estática com o Hibernate?

O uso de SQL estática exige que a cadeia de caractere SQL gerada pelo Hibernate seja exatamente a mesma a cada vez. Há um programa conhecido no Hibernate que faz com que o programa gere a mesma SQL, mas com aliases de coluna diferentes, ao longo do aplicativo. (Consulte este post do fórum no Web site do Hibernate para ver detalhes: como os nomes alternativos de colunas são gerados.)

Há duas formas de resolver esse problema para habilitar a SQL estática:

Configure o caminho da classe

O exemplo de aplicativo usa o Hibernate 3.2, o gerenciador de entidades e as anotações do Hibernate. Portanto, para compilar o aplicativo, é necessário que os seguintes arquivos JAR estejam no caminho da classe, junto com os outros arquivos JAR necessários para o Hibernate:

  • hibernate3.jar
  • hibernate-entitymanager.jar
  • hibernate-annotations.jar
  • hibernate-common-annotations.jar
  • ejb3-persistence.jar
  • dom4j-1.6.1.jar
  • log4j-1.2.15.jar
  • javassist-3.4.GA.jar
  • antlr-2.7.6.jar
  • commons-collections-3.1.jar
  • slf4j-api-1.5.2.jar
  • slf4j-log4j12-1.5.2.jar
  • commons-logging-1.0.4.jar
  • pdq-hibernate3.2.jar (vem com o Integration Module)

Para usar o IBM Integration Module, também é necessário que estes arquivos JAR estejam no caminho da classe:

  • pdq.jar
  • pdqmgmt.jar
  • Os JARs de db2jcc

Use o utilitário versionValidator para verificar os pré-requisitos

O Integration Module contém um programa chamado versionValidator, que faz a verificação de pré-requisitos do caminho da classe referente à versão do Hibernate, driver do JDBC e pureQuery Runtime. A Lista 4 mostra o comando que executa o programa.

Lista 4. Comando para executar o programa versionValidator

java  com.ibm.pdq.hibernate3.utility.VersionValidator

Se os arquivos JAR incluídos no caminho da classe estiverem no nível correto, o programa versionValidator exibe mensagens semelhantes às mostradas na Lista 5.

Lista 5. Saída do programa versionValidator quando todos os pré-requisitos estão corretos
>set CLASSPATH=./pdq.jar;./pdqmgmt.jar;./hibernate3.jar;./db2jcc.jar;./pdqhibernate3.jar;

>java    com.ibm.pdq.hibernate3.utility.VersionValidator

IBM integration module version: 2.2.0.3

Hibernate version: 3.3.1.GA

Found pdqmgmt.jar

PDQ runtime version: 2.18.121

IBM DB2 JDBC Universal Driver: 3.53

java version: 1.5.0_13

Se algum dos arquivos JAR incluídos no caminho da classe não estiverem no nível correto, o programa versionValidator mostra a mensagem de erro correspondente. Por exemplo: as mensagens da Lista 6 indicam que o driver de JDBC do DB2não está no nível correto para trabalhar com o Integration Module.

Lista 6. Saída do programa versionValidator com um pré-requisito incorreto
Hibernate version: 3.3.1.GA

Found pdqmgmt.jar

PDQ runtime version: 2.1.70

Found IBM DB2 JDBC Universal Driver version: 2.3 **** ERROR. Incorrect level. Requires 
        V3.53 or higher

java version: 1.5.0_13

Prepare o banco de dados do exemplo de aplicativo

Siga estas etapas para preparar o banco de dados do exemplo de aplicativo:

  1. Crie um banco de dados com o nome demodb. O Hibernate cria automaticamente as tabelas necessárias.
  2. Descompacte o arquivo DemoHibApp.zip e importe o exemplo de aplicativo como um projeto Java para a área de trabalho do Optim Development Studio.
  3. Inclua os mesmos arquivos JAR listados em Configure o caminho da classe no caminho de construção do projeto. É possível adicionar os arquivos JAR do pureQuery e do IBM Data Server para JDBC e SQLJ ao caminho de construção do projeto ao clicar com o botão direito no projeto e selecionar pureQuery > Add pureQuery support....

O exemplo de aplicativo usa as seguintes entidades:

  • CustomerInfo com a subclasse Customer
  • District
  • Item
  • Order

Gere o arquivo XML do pureQuery para execução da SQL estática

Use o comando HibernateGen a fim de gerar um arquivo test.pdqxml para o exemplo de aplicativo. O arquivo em lote para o comando (HibernateGen.bat) vem com o Integration Module. O caminho da classe deve conter todos os arquivos JAR de que o Hibernate precisa, junto com os seguintes arquivos:

  • pdq-hibernate3.3.jar
  • pdq.jar
  • pdqmgmt.jar e db2jcc.jar

Se você está usando o persistence.xml, a Lista 7 mostra os comandos para definir o caminho da classe para incluir os arquivos JAR obrigatórios e executar o comando HibernateGen .

Lista 7. Gerar o arquivo pdqxml usando HibernateGen para persistence.xml
> set CLASSPATH=./pdq.jar;./pdqmgmt.jar; ./db2jcc.jar;./pdq-hibernate3.3.jar;
./hibernate3.jar;./hibernate-entitymanager.jar;./hibernate-annotations.jar;
./hibernate-common-annotations.jar;./ejb3-persistence.jar;./dom4j-1.6.1.jar;
./log4j-1.2.15.jar;./javassist-3.4.GA.jar;./antlr-2.7.6.jar;
./commons-collections-3.1.jar;./slf4j-api-1.5.2.jar;./slf4j-log4j12-1.5.2.jar;
./commons-logging-1.0.4.jar;%CLASSPATH%

> HibernateGen -puName test

Se você está usando hibernate.cfg.xml, use o comando mostrado na Lista 8 para definir o caminho da classe e executar o comando HibernateGen .

Lista 8. Gere o arquivo pdqxml usando HibernateGen para hibernate.cfg.xml
> set CLASSPATH=./pdq.jar;./pdqmgmt.jar; ./db2jcc.jar;./pdq-hibernate3.3.jar;
./hibernate3.jar;./hibernate-entitymanager.jar;./hibernate-annotations.jar;
./hibernate-common-annotations.jar;./ejb3-persistence.jar;./dom4j-1.6.1.jar;
./log4j-1.2.15.jar;./javassist-3.4.GA.jar;./antlr-2.7.6.jar;
./commons-collections-3.1.jar;./slf4j-api-1.5.2.jar;./slf4j-log4j12-1.5.2.jar;
./commons-logging-1.0.4.jar;%CLASSPATH%

> HibernateGen

Após a conclusão do comando HibernateGen , certifique-se de que ele tenha criado um arquivo com o nome test.pdqxml no diretório src.

Nota: HibernateGen gera a SQL com o JDBC padrão para resultsetHoldability. Entretanto, o WebSphere Application Server usa um padrão diferente para o resultsetHoldability. Se você está implementando o aplicativo de Hibernate no WebSphere Application Server, verifique o resultsetHoldability da origem de dados do WebSphere Application Server e especifique-o no comando HibernateGen , como mostra a Lista 9.

Lista 9. HibernateGen para a configuração padrão do WebSphere Application Service
    > HibernateGen -resultsetHoldability 2

Há várias outras opções que podem ser usadas com o comando HibernateGen . Para obter uma lista de todas as opções disponíveis, emita o comando HibernateGen com a opção -help , como mostra a Lista 10.

Listagem 10. Lista as opções do comando HibernateGen
    > HibernateGen -help

Configure e ligue o arquivo XML do pureQuery para a execução da SQL estática

Para executar o aplicativo estático de forma estática, primeiramente é necessário configurar e depois ligar o arquivo test.pdqxml que foi gerado. Faça isso usando os comandos padrão do pureQuery Configure e StaticBinder como mostra a Lista 11. O comando StaticBinder cria os pacotes no servidor do DB2. Certifique-se de que pdq.jar, pdqmgmt.jar e os arquivos JAR do driver correspondente de JCC estejam no caminho da classe quando você executar esses comandos. Para obter mais informações sobre os comandos do pureQuery Configure e StaticBinder consulte a seção Recursos .

Listagem 11. Configure e ligue o arquivo XML do pureQuery
> java com.ibm.pdq.tools.Configure -rootPkgName test -pureQueryXml test.pdqxml

> java com.ibm.pdq.tools.StaticBinder

  -url jdbc:db2://localhost:50000/demodb

  -username xx

  -password xx

  -pureQueryXml test.pdqxml

  -traceFile demo_trace.txt

  -traceLevel ALL

Execute o aplicativo usando a SQL estática

A Lista 12 mostra as propriedades que são usadas no arquivo pdq.properties incluído no exemplo de aplicativo.

Listagem 12. Arquivo pdq.properties para o exemplo de aplicativo
pdq.captureMode=OFF
pdq.executionMode=STATIC
pdq.pureQueryXml=test.pdqxml

Essas definições são explicadas a seguir:

  • captureMode=OFF indica que a captura está desativada. A captura só precisa estar ativada quando você está usando o processo de otimização de cliente que é descrito mais adiante neste artigo.
  • executionMODE=STATIC indica que o modo de execução estático (e não dinâmico) deve ser usado.
  • pureQueryXml=test.pdqxml proporciona o nome e o local do terceiro arquivo XML do pureQuery que foi criado quando você executou o comando HibernateGen .

Para obter mais informações sobre todas as propriedades do pdq, consulte a seção Recursos .

No arquivo pdq.properties real incluído no exemplo de aplicativo, todas as propriedades estão com as linhas comentadas (cada linha começa com #). Antes de continuar, edite o arquivo, exclua os # caracteres para remover os comentários das três propriedades e salve o arquivo. Quando você terminar, o arquivo deve estar parecido com a Lista 12.

Se você está usando persistence.xml, agora pode executar o exemplo de aplicativo ao executar MainClient.java. Para executar MainClient.java no Optim Development Studio, clique com o botão direito no arquivo e selecione Run As > Java Application. As instruções SQL do aplicativo são executadas de forma estática.

Se estiver usando hibernate.cfg.xml, execute o exemplo de aplicativo ao executar MainClientSessionFactory.java. Observe que hibernate.cfg.xml usa a classe de configuração fornecida pelo Integration Module, como mostra a Lista 13. Isso é necessário para resolver o problema descrito na seção Por que a alteração de Provider é obrigatória para possibilitar o uso de SQL estática com o Hibernate? .

Lista 13. Uso da classe Configuration fornecida pelo Integration Module nos aplicativos de hibernate.cfg.xml
public static void main(String[] args) {
	
    _sFactory = new PDQAnnotationConfiguration().configure()
						.buildSessionFactory();

Se você está implementando e executando o exemplo de aplicativo no WebSphere Application Server, consulte o link na seção Recursos a respeito da otimização de cliente do pureQuery em ambientes de aplicativos Web.


Habilitando os lotes heterogêneos do pureQuery para aplicativos do Hibernate

Defina as propriedades em persistence.xml

Para habilitar lotes heterogêneos de pureQuery com aplicativos de Hibernate 3.2 usando o IBM Integration Module, é necessário certificar-se de que as seguintes propriedades estejam especificadas no arquivo persistence.xml:

  • hibernate.jdbc.factory_class deve ser definida como com.ibm.pdq.hibernate3.batcher.PDQBatcherFactory
  • hibernate.ejb.event.flush deve ser definida como com.ibm.pdq.hibernate3.ejb3.listener.PDQEJB3FlushEventListener

O exemplo de aplicativo inclui essas propriedades em uma seção de comentários de persistence.xml. Portanto, no exemplo de aplicativo, é possível simplesmente editar o arquivo persistence.xml file, remover os comentários das propriedades e salvar. Com os comentários removidos, esta seção do arquivo ficará parecida com a Lista 14.

Listagem 14. Propriedades obrigatórias em persistence.xml para habilitar os lotes de pureQuery
<property name="hibernate.jdbc.factory_class" value = 
"com.ibm.pdq.hibernate3.batcher.PDQBatcherFactory"/>

<property name="hibernate.ejb.event.flush" value = 
"com.ibm.pdq.hibernate3.ejb3.listener.PDQEJB3FlushEventListener"/>

<property name="hibernate.connection.provider_class" value= 
"org.hibernate.connection.C3P0ConnectionProvider"/>

Configure o armazenamento das instruções em cache

Para ter um bom desempenho, é importante que o armazenamento em cache das instruções esteja ativado e configurado com um tamanho razoável. Os aplicativos de Hibernate podem usar o conjunto de conexões c3p0 para habilitar o armazenamento das instruções em cache em aplicativos de J2SE. Para habilitar o armazenamento das instruções em cache em c3P0, defina hibernate.connection.provider_class como org.hibernate.connection.C3P0ConnectionProvider em persistence.xml, como foi mostrado acima, na Lista 14.

Nos aplicativos de J2EE, é possível definir o armazenamento das instruções em cache no servidor de aplicativos.

O arquivo c3p0.properties especifica o tamanho do cache de instruções, como mostra a Lista 15.

Listagem 15. Especificação do tamanho do arquivo c3p0
c3p0.maxStatementsPerConnection = 200

O tamanho especificado para o cache de instruções deve ser relativamente grande. Normalmente, fica na faixa de 100 a 200. Em um ambiente de J2SE, se o cache de instruções for pequeno demais ou o tamanho do lote for grande demais, é possível que você receba exceções de SQL resultantes de inconsistências no cache de instruções.

Configure hibernate.cfg.xml

Se o aplicativo de Hibernate estiver usando a API nativa do Hibernate, será necessário especificar as seguintes propriedades no arquivo hibernate.cfg.xml:

  • hibernate.jdbc.factory_class deve ser definida como com.ibm.pdq.hibernate3.batcher.PDQBatcherFactory
  • A classe de listener de eventos de flush deve ser definida como com.ibm.pdq.hibernate3.listener.PDQFlushListener

O exemplo de aplicativo inclui essas propriedades em seções de comentários de hibernate.cfg.xml. Portanto, no exemplo de aplicativo, é possível simplesmente editar o arquivo hibernate.cfg.xml, remover os comentários das propriedades e salvar. Com os comentários removidos, as seções do arquivo ficarão parecidas com a Lista 16.

Listagem 16. Propriedades obrigatórias em hibernate.cfg.xml para habilitar os lotes de pureQuery
<property name="hibernate.jdbc.factory_class">
     com.ibm.compdq.hibernate3.PDQBatcherFactory</property> 
<event type="flush">
<listener class="com.ibm.pdq.hibernate3.listener.PDQFlushListener"/>
</event>

Execute o aplicativo com lotes heterogêneos

A Lista 17 mostra o arquivo persistence.xml configurado para executar o exemplo de aplicativo com a SQL estática de pureQuery e os lotes heterogêneos habilitados. Define as entidades, propriedades de conexão com o banco de dados e outras propriedades de configuração obrigatórias.

A propriedade batch_size controla o tamanho do lote de JDBC. Também é usada pelo Integration Module para controlar o tamanho de um lote de pureQuery. O tamanho recomendado para os lotes fica na faixa de 50 a 100. A maioria dos benefícios dos lotes é observada na faixa de 1 a 25. Se o lote for grande demais, é possível que você receba uma exceção de SQL com o código SQL -805. Isso significa que o servidor de banco de dados ficou sem cursores dinâmicos.

Listagem 17. persistence.xml para o exemplo de aplicativo de Hibernate
<persistence-unit name="test" transaction-type="RESOURCE_LOCAL">

<provider>com.ibm.pdq.hibernate3.PDQHibernatePersistence</provider>
<!-- <provider>org.hibernate.ejb.HibernatePersistence</provider> -->

    <class>demo.CustomerInfo</class>     
    <class>demo.Customer</class> 
    <class>demo.District</class>
    <class>demo.Item</class>
    <class>demo.Order</class>
 		
<properties>
<property name="hibernate.connection.driver_class"
value="com.ibm.db2.jcc.DB2Driver"/>
					
<property name="hibernate.connection.url" 
value="jdbc:db2:demodb"/>
					
<property name="hibernate.connection.username" 
value="xx"/>
					
<property name="hibernate.connection.password" 
value="xx"/>  
        
<property name="hibernate.dialect" value="org.hibernate.dialect.DB2Dialect"/>

<property name="hibernate.hbm2ddl.auto" 
value="update"/>

<property name="hibernate.jdbc.batch_size" 
value = "100"/>

<property name="hibernate.jdbc.factory_class" value = 
"com.ibm.pdq.hibernate3.batcher.PDQBatcherFactory"/>

<property name="hibernate.ejb.event.flush" value = 
"com.ibm.pdq.hibernate3.ejb3.listener.PDQEJB3FlushEventListener"/>

<property name="hibernate.connection.provider_class" value= 
"org.hibernate.connection.C3P0ConnectionProvider"/>

</properties>
</persistence-unit>

Nota: Se você está usando o Informix Dynamic Server, é necessário definir a propriedade hibernate.dialect em persistence.xml como InformixDialect da seguinte forma:
<property name = “hibernate.dialect” value = “org.hibernate.dialect.InformixDialect”/>

Agora é possível executar o exemplo de aplicativo ao executar MainClient.java. O processador de lotes personalizado do pureQuery garante a ocorrência de lotes heterogêneos.

Se está usando hibernate.cfg.xml, execute o exemplo de aplicativo ao executar a classe MainClientSessionFactory.java , que usa a API SessionFactory. Também se deve incluir o arquivo c3p0.properties no caminho do aplicativo com a propriedade c3p0.maxStatementsPerConnection especificada.


Comparando o desempenho de tempo decorrido do exemplo de aplicativo

Esta seção descreve como determinar se o desempenho do exemplo de aplicativo melhora ao executá-lo com os lotes heterogêneos do pureQuery.

Reúna o tempo decorrido

Para determinar se os lotes heterogêneos do pureQuery fornecem um benefício referente ao tempo decorrido ao executar o exemplo de aplicativo, é necessário executá-lo com os lotes heterogêneos e sem eles.

Um método de obter o tempo decorrido é executar o aplicativo usando MainClient.java ou MainClientSessionFactory.java. Cada uma dessas alternativas mostra o tempo decorrido total que é necessário para a execução do programa.

Outro método é ativar o rastreamento do processador de lotes. Isso permite ver como o Integration Module efetivamente está criando os lotes heterogêneos, ao mostrar quando o lote iniciou, quando as instruções são adicionadas ao lote e quando o lote termina. O exemplo de aplicativo inclui um arquivo chamado log4j.properties que pode ser usado para ativar o rastreamento do processador de lotes. Depois que o lote termina, o diretório atual contém um arquivo chamado demo.log que contém mensagens semelhantes às mostradas na Lista 18.

Listagem 18. Mensagem de rastreio em demo.log
TRACE main com.ibm.pdq.hibernate3.batcher.PDQBatcher - PureQuery batch started

Added to the batch: insert into District (d_city, d_name, d_next_o_id, 
   d_state, d_street_1, d_street_2, d_tax, d_ytd, d_zip, version, d_id) 
   values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

Added to the batch: insert into Customer (city, fname, lname, state, 
  street, version, zipcode, c_balance, c_credit, c_credit_lim, c_data, 
  c_delivery_cnt, c_discount, c_payment_cnt, c_since, c_ytd_payment, 
  district_d_id, c_d_id, c_id) 
   values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

Added to the batch: insert into Item (i_data, i_name, i_price, version, i_id) 
   values (?, ?, ?, ?, ?)

Added to the batch: insert into Order (district_d_id, itime, o_all_local, o_c_id, 
    o_carrier_id, o_entry_d, o_ol_cnt, version, o_d_id, o_id) 
      values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

Added to the batch: update District set d_city=?, d_name=?, d_next_o_id=?, d_state=?, 
    d_street_1=?, d_street_2=?, d_tax=?, d_ytd=?, d_zip=?, version=? 
       where d_id=? and version=?

Added to the batch: update Customer set city=?, fname=?, lname=?, state=?, street=?, 
  version=?, zipcode=?,    c_balance=?, c_credit=?, c_credit_lim=?, c_data=?, 
   c_delivery_cnt=?, c_discount=?, c_payment_cnt=?, c_since=?, c_ytd_payment=?, 
    district_d_id=? where c_d_id=? and c_id=? and version=?

Added to the batch: update Item set i_data=?, i_name=?, i_price=?, version=? 
   where i_id=? and version=?

TRACE main com.ibm.pdq.hibernate3.batcher.PDQBatcher - About to execute the batch
TRACE main com.ibm.pdq.hibernate3.batcher.PDQBatcher - Batch Executed.
  Executed batch size=7
TRACE main com.ibm.pdq.hibernate3.batcher.PDQBatcher - Number of batches 
   executed in the session = 1

Resultados do exemplo

Os autores deste artigo testaram o exemplo de aplicativo com o tamanho do lote configurado como 100, em relação ao DB2 em uma máquina local e em uma máquina remota. Esse teste teve os seguintes resultados no DB2 para Linux, UNIX e Windows:

Renúncia de responsabilidade

Os dados de desempenho contidos neste documento foram determinados em vários ambientes controlados de laboratório e servem apenas como referência. Os clientes não devem adaptar esses números de desempenho aos seus próprios ambientes como padrões de desempenho do sistema. Os resultados que podem ser obtidos em outros ambientes operacionais podem apresentar uma variação significativa. Os usuários deste documento devem verificar os dados aplicáveis ao seu ambiente específico.

  • Com o DB2 e o exemplo de aplicativo executando em uma máquina local, o pureQuery melhorou o desempenho de tempo decorrido em relação ao JDBC em mais de 40%, dependendo do número de objetos por transação. A Figura 7, abaixo, descreve esse fato. São criadas sete instruções SQL por objeto (por sua vez, são criados7 objetos de entidade diferentes por objeto).
  • Com o DB2 executando em uma máquina remota e o exemplo de aplicativo executando em uma máquina local, as melhorias no desempenho de tempo decorrido variaram entre 12% e mais de 50%, dependendo do número de objetos por transação. A Figura 8, abaixo, descreve esse fato. São criadas sete instruções SQL por objeto (por sua vez, são criados 7 objetos de entidade diferentes por objeto).

Na Figura 7, o eixo X representa o número de objetos por transação. O eixo Y representa o tempo decorrido necessário para realizar a transação, em milissegundos. Observe que o gráfico indica que o tempo decorrido referente aos lotes do JDBC é maior que o tempo decorrido referente ao pureQuery.

Figura 7. JDBC X pureQuery com o servidor de banco de dados local

Na Figura 8, o eixo X representa o número de objetos por transação. O eixo Y representa o tempo decorrido necessário para realizar a transação, em milissegundos. Observe que o gráfico indica que o tempo decorrido referente aos lotes do JDBC é maior que o tempo decorrido referente ao pureQuery. Observe também que, nesse caso, conforme o número de objetos por transação aumenta, a variação do tempo decorrido entre o pureQuery e o JDBC aumenta.

Figura 8. JDBC X pureQuery com o servidor de banco de dados remoto

Usando SQL estática e lotes heterogêneos juntos

Os recursos de SQL estática e de lotes heterogêneos são ortogonais. Isso significa que um aplicativo de Hibernate pode usar SQL estática e lotes heterogêneos juntos, ao mesmo tempo, ou usar cada recurso de forma independente. Não há sobreposição de etapas na configuração de cada recurso. Para configurar a SQL estática, siga as etapas listadas em Habilitando a SQL estática do pureQuery para aplicativos de Hibernate. Para configurar os lotes heterogêneos, siga as etapas listadas em Habilitando os lotes heterogêneos do pureQuery para aplicativos do Hibernate. Para configurar ambos, basta seguir as etapas das duas seções; a ordem não importa.


Usando a captura incremental para reunir consultas de Criteria

Se o aplicativo do Hibernate usa consultas de Criteria, é possível usar a captura incremental para obter a SQL das consultas de Criteria e convertê-la para SQL estática. Para fazer isso, altere pdq.properties como mostra a Lista 19. (Existe o planejamento de futuras versões de HibernateGen.bat para suportar a geração da SQL para as consultas de Criteria.)

Listagem 19. pdq.properties para captura incremental
pdq.captureMode=ON
pdq.executionMode=STATIC
pdq.pureQueryXml=test.pdqxml
pdq.OutputPureQueryXml=incremental_capture.pdqxml

Quando você executa o aplicativo, ele cria um arquivo novo com o nome incremental_capture.pdqxml, que contém as SQLs que não estão presentes no arquivo pdqxml criado pelo comando HibernateGen . É possível usar o utilitário Merge do pureQuery para mesclar os dois arquivos. Dessa forma, você obtém um único pdqxml consolidado que contém as SQLs dos dois arquivos. A Lista 20 mostra um exemplo de execução do utilitário Merge.

Listagem 20. Executando o utilitário Merge do pureQuery
> java com.ibm.pdq.tools.Merge

  -outputPureQueryXml test_Merged.pdqxml

  -baseFile test.pdqxml

  -inputPureQueryXml incremental_capture.pdqxml

Para obter mais informações sobre o utilitário Merge do pureQuery, consulte a seção Recursos .

Após a execução do exemplo do utilitário Merge mostrado na Lista 20, o arquivo test_Merged.pdqxml está pronto para a ligação. Primeiro, execute o StaticBinder em test_Merged.pdqxml, conforme o explicado na Lista 11.. Em seguida, altere pdq.properties como se mostra abaixo, na Lista 21.

Listagem 21. pdq.properties para execução de SQL estática depois da captura incremental
pdq.captureMode=OFF
pdq.executionMode=STATIC
pdq.pureQueryXml=test_Merged.pdqxml

Execute o aplicativo novamente. Agora a SQL que vem das consultas de Criteria também executará de forma estática.


Conclusão

Este artigo é o primeiro de uma série com duas partes. Descreveu como usar o IBM Integration Module para pureQuery e Hibernate com aplicativos de Hibernate (aplicativos de Hibernate JPA e aplicativos nativos de Hibernate). Também forneceu uma breve visão geral de como usar a captura incremental para otimização de clientes do pureQuery e medições informais de desempenho em termos de tempo decorrido. A Parte 2 da série focará os aplicativos de iBATIS.

O IBM Integration Module para pureQuery e Hibernate proporciona ganhos significativos de desempenho no DB2 ao usar SQL estática. Também oferece benefícios significativos em relação ao tempo decorrido em servidores de DB2 e Informix quando são usados lotes heterogêneos com aplicativos adequados. Essas melhorias de desempenho se aplicam a ambientes J2EE e J2SE.


Agradecimentos

Os autores agradecem a Asim Singh e Ambrish Bhargava pela revisão do artigo e pelo excelente feedback.


Download

DescriçãoNomeTamanho
Sample Hibernate application for this articleDemoHibApp.zip27KB

Recursos

Aprender

Obter produtos e tecnologias

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Information Management, Software livre, Tecnologia Java
ArticleID=516660
ArticleTitle=Acelere aplicativos de Hibernate e iBATIS usando o pureQuery, Parte 1: Usando o IBM Integration Module para Hibernate e pureQuery
publish-date=05122014