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!