Hibernate com mais de um banco de dados

5 respostas
kemperacc

Srs, bom dia.

Tenho um sistema que utiliza hibernate no lado do servidor, ele esta desenvolvido sobre a seguinte arquitetura:

MYSQL < - > SERVER JAVA <--------- (rede) -----------> APP Swing

Sendo que como ja disse, o server java utiliza hibernate para persistencia. A camada de rede é via RMI.

Surgiu agora a necessidade do server java trabalhar com mais de um banco de dados, ou seja, um banco de dados para cada empresa, assim, na app swing no momento que o cara for acessar ele deve indicar qual empresa esta abrindo.

Resolvemos então que o que melhor enquadraria em nossa arquitetura seria:

Fazer 2 bancos de dados, um para cada empresa. Esses bancos seriam idênticos quanto a estrutura;
A cada chamada via RMI, hoje é passado um objeto UserSession (que indica a sessao que o usuario abriu) esse objeto usersession passaria a conter a propriedade databaseName, o que faria com que o servidor soube-se em qual banco executar a operacao, exemplo:

//HOJE EH ASSIM:

public void salvaCliente(UserSession userSession, Cliente cliente) throws RemoteException, RegistroDuplicadoException, CPFInvalidoException (....){

         Session sessao = super.getSession();
         Transaction tx = sessao.beginTransaction();

         //(.....)

        sessao.saveOrUpdate(cliente);

        tx.commit();

}

O super.getSession() obtem uma sessao do hibernate, ja que essa classe extend a minha classe DBUtils.

Entao creio que o modo mais facil de obter a sessao com o banco correto seria passar o nome do banco para essa getSession(), assim:

//Ficaria assim:
public void salvaCliente(UserSession userSession, Cliente cliente) throws RemoteException, RegistroDuplicadoException, CPFInvalidoException (....){

         Session sessao = super.getSession(userSession.getDBName());
         Transaction tx = sessao.beginTransaction();

         //(.....)

        sessao.saveOrUpdate(cliente);

        tx.commit();

}


//funcao getsession da classe dbUtils:

    public Session getSession() {
        return this.hibernate.getSession();
    }

//e no construtor da classe esta assim:
this.hibernate = new HibernateUtils();

Alguem poderia me dar uma luz?

5 Respostas

R

Poderia colocar o código do seu HibernateUtils no momento que você cria a session factory? Assim posso ajudar mais.

Para trabalhar com mais de um banco é facil se realizar a configuração em runtime.

sergiotaborda

kemperacc:
Srs, bom dia.

Tenho um sistema que utiliza hibernate no lado do servidor, ele esta desenvolvido sobre a seguinte arquitetura:

MYSQL < - > SERVER JAVA <--------- (rede) -----------> APP Swing

Sendo que como ja disse, o server java utiliza hibernate para persistencia. A camada de rede é via RMI.

Surgiu agora a necessidade do server java trabalhar com mais de um banco de dados, ou seja, um banco de dados para cada empresa, assim, na app swing no momento que o cara for acessar ele deve indicar qual empresa esta abrindo.

Resolvemos então que o que melhor enquadraria em nossa arquitetura seria:

Fazer 2 bancos de dados, um para cada empresa. Esses bancos seriam idênticos quanto a estrutura;
A cada chamada via RMI, hoje é passado um objeto UserSession (que indica a sessao que o usuario abriu) esse objeto usersession passaria a conter a propriedade databaseName, o que faria com que o servidor soube-se em qual banco executar a operacao, exemplo:

Essa é uma péssima opção. O correto é ter um sistema (e portanto um banco) multi-locatário ( multi-tennat) onde um banco dá conta de todos os clientes. Esta é solução adotada em muitos lugares e a base para o Software as Service. Imagine dar manutenção em N bancos de dados onde N é o numero de clientes…

kemperacc

Serao so 2 bancos…

kemperacc

RafaelViana:
Poderia colocar o código do seu HibernateUtils no momento que você cria a session factory? Assim posso ajudar mais.

Para trabalhar com mais de um banco é facil se realizar a configuração em runtime.

public class HibernateUtils {

    private SessionFactory factory;
    private Configuration cfg;

    public HibernateUtils() throws ConnectException, HibernateException, Exception {
        try {
            cfg = new Configuration();
            cfg.configure();
            factory = cfg.buildSessionFactory();
        } catch (Exception ex) {
            ex.printStackTrace();
            throw ex;
        }
    }

    public Session getSession() {
        return factory.openSession();
    }
}

Eu ja notei que esse metodo factory.openSession() aceita um obj Connection como parametro. Seria uma conexao jdbc com o mysql por exemplo?

Se for ta facil!

Obrigado.

R

Você configura o hibernate ao chamar esse método, como não passa nenhum parametro ele assume o arquivo de configuração padrão: hibernate.cfg.xml

cfg.configure();

Se quiser faça o seguinte teste, coloque um arquivo hibernate2.cfg.xml na mesma pasta onde está esse xml e aponta para outro banco de dados.Ai você configura assim:

cfg.configure("hibernate2.cgf.xml");

Outra possibilidade é sem usar o xml, onde você recebe um id e partir desse você busca em um banco de dados o endereco, usuario e senha de seu cliente (bom para muitos clientes).

cfg.setProperty("hibernate.connection.url", cliente.endereco);
cfg.setProperty("hibernate.connection.username", cliente.usuario);
cfg.setProperty("hibernate.connection.password", cliente.senha);
cfg.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLInnoDBDialect");
cfg.setProperty("hibernate.show_sql", "false");
cfg.setProperty("hibernate.format_sql", "true");
cfg.setProperty("hibernate.hbm2ddl.auto", "update");
cfg.setProperty("hibernate.connection.provider_class", "org.hibernate.connection.C3P0ConnectionProvider");
cfg.setProperty("hibernate.c3p0.max_size", "20");

cfg.buildSessionFactory();

Esses dados tanto o nome do arquivo para a situação 1, como o id para buscar na situação 2, é como se fossem o serial, a key para esse cliente.

Ao criar a sessionFactory você mantém ela em um Map, onde cada key do cliente está vinculado com uma factory.Então, antes de criar você verifica, se já existe um factory criada para esse cliente utiliza ela, caso não exista cria uma nova e depois guarda ela na lista.

Seria isso, qualquer dúvida pergunta ai.Se quiser posto o código que uso aqui.

Criado 14 de maio de 2010
Ultima resposta 14 de mai. de 2010
Respostas 5
Participantes 3