Estou desenvolvendo uma aplicação que vai acessar bancos diferentes, mas com o mesmo schema.
Dependendo do login do usuário ele vai acessar determinado banco de dados.
Existe a possibilidade de injetar o entityManager com o persistenceUtil com as configurações do banco do usuário em tempo de execução.
Alguma outra ideia para fazer isso?
Tipo assim tu vai ter Oracle e Postgresql, e tu vai setar valores nos 2 ou trocar valores entre eles ?
L
lfcdtv
cada cliente vai ter seu banco e só poderá persistir nele!
G
garcia-jj
Isso é um recurso chamado multi-tenancy e não está associado ao VRaptor, mas sim a persistencia (JPA/Hibernate).
Atualmente nenhuma ferramenta de ORM possui suporte nativo a multi-tenancy, e como em ambiente JTA você precisa que o JPA construido na inicialização do container, há duas soluções:
Criar um datasource para cada cliente, e um entity-manager para cada cliente. Assim você precisa decidir qual entity manager injetar com o uso de qualifiers do CDI.
No Oracle você pode usar um dblink, que nada mais é que uma conexão remota ao outro banco. Tenho usado isso em um projeto atual, onde eu possuo um banco master e os bancos dos clientes. A base master possui os links para as outras bases, e é injetada no entity-manager. Com uso de um query-interceptor eu reescrevo cada query com o banco do cliente, algo como: de select * from contas para select * from contas@cliente01.
O Hibernate 4 está com suporte a multi-tenancy, e tem até uma webminar com o Emmanuel Bernard, um dos desenvolvedores do Hibernate, explicando as diversas estratégias de tenant. Procure por isso no vimeo.com/jbossdeveloper.
R
RafaelViana
Você vai usar o que para determinar qual banco de dados acessar? Essa informação será passada a cada request ou estará na sessão?
se isso for direto (cada usuário/tenant acessa um e somente um banco), vc pode criar um ComponentFactory que recebe o usuário no construtor (vc vai precisar prover esse usuário de algum jeito) e retorna a EntityManagerFactory correta.
Lembre-se de cachear as EntityManagerFactory
L
lfcdtv
Lucas,
No caso o persistence.xml teria um persistence-unit para cada configuração dos bancos.
No caso o persistence.xml teria um persistence-unit para cada configuração dos bancos.
Não sou o Lucas, mas pelo que entendi da solução dele, sim, você precisa ter um persistence-unit para cada tenant. Atualmente não é possível ter mais de uma conexão por entity-manager. Talvez com o Hib4 seja possível, mas não sei informar porque ainda não olhei como é feito o multi-tenancy deles.
Lucas_Cavalcanti
uma persistence-unit e uma EntityManagerFactory pra cada user/tenant
essa abordagem de multi-tenant torna bem difícil o deploy de um novo usuário/tenant.
então a menos que vc tenha duas componentFactory registradas, tá tudo certo. Dê um clean no projeto e no servidor e reinicie o servidor, e teste de novo por favor
L
lfcdtv
Lucas,
Criei dois componentes (EntityManager e EntityManagerFactory) e funcionou!
L
lfcdtv
Lucas,
Em relação ao cache dos componentes, seria uma cache de segundo nível, por exemplo utilizando o EhCache?
Lucas_Cavalcanti
cachear = não recriar as EntityManagerFactory.
tanto faz como vc faz isso…
pode até ser com um Map<AlgumaCoisa, EntityManagerFactory> no component factory