Gambiarra esperta: trabalhando com mais de um banco de dados usando Hibernate (ou qualquer ferramenta ORM)

Hibernate é fenomenal, mas tem um problema: quando precisamos lidar com mais de um banco de dados, as coisas se complicam. Neste post pretendo mostrar como superar esta “limitação” do Hibernate usando um padrão (confesso: orientado a gambi, mas funciona bem!) que facilita esta tarefa.

Porém, antes de começar, vamos supor a seguinte situação: existem dois bancos de dados: bdUsuarios, aonde estão armazenadas informações relativas aos usuários do seu sistema e outro, chamado bdNegocios, aonde ficam as tabelas relativas às suas classes de negócio.

Para piorar um pouco mais a situação, vamos supor que todas as suas classes relativas ao gerenciamento de seus usuários já se encontrem prontas, armazenadas em um arquivo jar (traduzindo: já se encontram inclusive mapeadas para acessar os dados presentes no banco de dados bdUsuarios).

Ok: suponhamos agora que exista uma classe chamada Evento, que encontre-se definida tal como no código abaixo:

class Evento {
          private String id
          private Date data
          private Usuario usuario
          private String mensagem
          // gets e sets omitidos
}

Os dados da classe Evento deverão ser armazenados no banco de dados bdNegocios. A primeira coisa que poderá passar pela cabeça do leitor será: “hmm… bastaria alterar as configurações de acesso ao banco de dados do Hibernate!”. Porém, a solução é bem mais simples. Basta criar o que chamo de “propriedades ORM only“.

Uma propriedade ORM only seria aquela utilizada APENAS pelo mecanismo de ORM. No nosso caso, suponhamos que queiramos armazenar os dados referentes à classe Evento na tabela evento, cuja estrutura encontra-se exposta abaixo:

   create table evento (
          id varchar(36) not null,
          idUsuario varchar(36) not null, 
          data timestamp not null,
          mensagem varchar(255) not null,
          primary key(id)
    )

Incluiriamos as nossas propriedades ORM only em nossa classe Evento tal como no código abaixo:

  (...)
   // Para uso somente do ORM
   public String getIdUsuario() {
         return getUsuario() == null ? null : getUsuario().getId();
   }

   // Para uso somente do ORM
   public void setIdUsuario(String valor) {
         // Suponha que exista um construtor para usuario que carregue seus dados a partir do id
         try {
               setUsuario(new Usuario(valor));
           } catch (ErroUsuarioNaoEncontrado ex) {
              setUsuario(null);
           }
   }
  (...)

Em seguida, vamos ao nosso arquivo de mapeamento da classe Evento:

(...)
<class name="meupacote.Evento" table="evento">
     <id name="id" column="id">
          <generator class="uuid"/>
     </id>
     <property name="data"/>
     <property name="mensagem"/>
     <!-- O pulo do gato! -->
     <property name="idUsuario" column="idUsuario"/>
</class>

No mapeamento, mapeamos uma propriedade chamada idUsuario, que corresponderá à respectiva ORM only de nossa classe Evento. O Hibernate pensará que se trata de apenas uma propriedade do tipo varchar(36), no entanto, no interior do set e do get, estaremos, na realidade, lidando com a classe Usuario.

Como já mencionei, trata-se de uma solução um tanto quanto “gambi”, no entanto, foi a única que encontrei para solucionar o problema e, espero, o seu também!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.