| Autor |
Mensagem |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 30/05/2009 17:35:30
|
rafaelbnc
Thread.start()
![[Avatar]](/images/avatar/b47122497e685d3a5ebbc85f018d1936.jpg)
Membro desde: 09/01/2007 11:24:31
Mensagens: 39
Offline
|
Estou pensando em trabalhar com um banco de dados (Postgresql) em um
sistema da seguinte forma:
No esquema public (default do postgresql) eu tenho só uma tabela de
usuários com os campos login, senha e esquema.
Quando o usuário efetuar login o sistema verifica o esquema e faz o
hibernate trabalhar em cima do esquema desse usuário.
Todos os esquemas tem as mesmas tabelas exemplo:
Schema: User01; Tabelas: usuario, endereço, dependentes, produtos...
Schema: User02; Tabelas: usuario, endereço, dependentes, produtos...
O sistema é online e pode ter mais de um usuário logado ao mesmo
tempo.
Alguém já trabalho dessa forma e sabe como fazer a troca dinâmica de
esquemas com o Hibernate?
É realmente vantajoso trabalhar desta forma, tendo em vista que, nesse
sistema, os dados de cada usuário só são pertinentes a ele mesmo?
--
Rafael de Paula Souza
Sublimus - Desenvolvimento de Software e Soluções Web.
www.sublimus.com.br
|
|
|
 |
|
|
![[Post New]](/templates/default/images/icon_minipost_new.gif) 30/05/2009 18:15:06
|
GraveDigger
JavaEvangelist
![[Avatar]](/images/avatar/3332880692313818482a5a0286608ab6.jpg)
Membro desde: 07/07/2005 13:47:12
Mensagens: 354
Localização: Aracajú
Offline
|
Boa Noite,
Cara, sem querer te desanimar, mas vc está em apuros
Atualmente estou trabalhando numa arquitetura que é próxima a essa(na verdade, ainda pior) mas tem essa característica de 1 schema por cliente.
Vc não vai "trocar" de esquema de um usuário para o outro, vc precisa ter um SessionFactory distinto POR schema.
Se vc tiver 100 clientes, terá que ter 100 sessionFactories.
Essa arquitetura vem ganhando certo espaço mas infelizmente não há nada que te ajude a lidar com isso atualmente.
Consegui desenvolver uma solução bem legal mas ela usa o framework Seam.
Se vc estiver usando ele tb, posso te ajudar(acredito que com outro framework, como o Spring, o tipo de configuração que eu fiz não funcionaria, mas conheço muito pouco do Spring para afirmar isso com certeza)
Se vc estiver ainda na hora da modelagem, prefira o modelo convencional, caso contrário, terá que fazer o que eu falei.
Não se aventure em tentar mudar o schema de uma determinada Session(ou mesmo sessionFactory) em tempo de execução, será um grande desperdício de tempo.
Abs,
Pedro Sena
|
SCWCD
SCJP
Pedro Henrique Lobato Sena
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 30/05/2009 20:56:57
|
rafaelbnc
Thread.start()
![[Avatar]](/images/avatar/b47122497e685d3a5ebbc85f018d1936.jpg)
Membro desde: 09/01/2007 11:24:31
Mensagens: 39
Offline
|
Obrigado GraveDigger,
A minha sorte é que estou utilizando Seam e vou te pedir para me enviar a tua solução.
Mas é uma pena que o Hibernate não tenha um suporte fácil a essa arquitetura, você já deu uma olhada se alguém já submeteu esse feature para o pessoal do Hibernate?
--
Rafael de Paula Souza
Sublimus - Desenvolvimento de Software e Soluções Web.
www.sublimus.com.br
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 30/05/2009 21:58:00
|
GraveDigger
JavaEvangelist
![[Avatar]](/images/avatar/3332880692313818482a5a0286608ab6.jpg)
Membro desde: 07/07/2005 13:47:12
Mensagens: 354
Localização: Aracajú
Offline
|
Oi,
Que garoto de sorte vc por estar usando o Seam
Bom, existe um projeto do hibernate chamado Shards, mas ainda está muito cru, inviável para um ambiente de produção.
Ele visa trabalhar com arquiteturas como a nossa e oferece algumas coisas mais complexas(que eu precisei, mas vc não vai) como um "join cross-schema"
Bom, eu ia bloggar sobre essa solução se eu tivesse saco e tempo pra manter um blog, como não é o caso, vou tentar ser sucinto aqui indicando os passos que fiz, caso vc encontre dificuldade em algum , vou te ajudando com código na medida que eu puder, pq a solução completa é grande e não posso expor os fontes por completo.
1) Crie um hibernate.cfg.xml e coloque suas propriedades específicas de banco lá(Cuidado para não colocar um name na parte session-factory se não ele vai atribuir ao JNDI). Não coloque atributos específicos de algum esquema, como connection.url, user_name ou password(mto menos dataSource)
2) Crie uma classe que possa montar sua SessionFactory a partir desse arquivo, o típico HibernateUtil, mas coloque ele como um componente Seam, deixe-o Stateless. Lembre-se, o método deve retornar a SessionFactory, e não armazená-la em alguma variável. Esse método vai receber como parâmetro um Usuario de seu sistema, procure deixar na tabela do seu usuário o nome do schema ao qual ele vai se conectar, importante essa info lá.
Aqui vc vai informar, programaticamente, as configurações que vc não passou no passo 1, para que seja tudo relativo ao usuário que entrou como parâmetro do método.
3) Por motivos de performance, é melhor vc iniciar todas suas SessionFactories em tempo de deploy, para isso vamos criar um SessionFactoryPreloader. Essa classe vai ler do banco 'global'(aquele que não é específico de cada usuário) todos os usuário cadastrados para que vc possa montar suas respectivas SessionFactories, mais abaixo mostro como vc vai conectar nesse banco. Ainda nessa classe, sempre que vc criar uma SessionFactory(vc vai fazer um loop para cada cliente seu) vc vai jogar ela em escopo de aplicação usando como alias aquele atributo que especifiquei no item 2, eu estou usando o nome do schema do usuario em questão, que é um atributo que está na minha classe Usuário.
Edit: Para que sua classe suba em tempo de deploy, não se esqueça de anotá-la com @Startup, essa classe deve ser ScopeType.APPLICATION tb
4) Vamos agora criar uma classe que possa nos devolver a sessionFactory correta dado um usuario, isso será usado no item seguinte.
Algo bem simples como:
Como você pode ver, devemos ter em algum escopo(de preferencia session) a variável customer, que é o usuário dono do schema ao qual queremos conectar
5) Agora vem a mágica do seam, aqui que você vê de fato a diferença dele
No seu components.xml, coloque o seguinte:
Como você pode ver, estamos usando #{correctSessionFactory} como a sessionFactory correta, ai que está o truque, ele só vai dar um evaluate nessa expressão quando vc solicitar a hibernateUserSession, ou seja, em tempo de execução, e quando isso acontecer, ela terá um valor, desde que você tenha um usuário em sessão.
Basicamente a idéia é essa, o acesso ao seu banco 'global' pode ser configurado da forma convencional, a partir dele vc obtem o usuário correto e joga-o no escopo Session do Seam, daí pra frente, caso você tenha feito todos esses passos que te disse, sempre que vc precisar da sessão do usuário você pode injetá-la via #{hibernateUserSession} que o Seam se encarrega de jogar lá justamente a session que você precisa.
Qualquer dúvida posta ai que eu procuro ajudar,
Abraço,
Pedro Sena
This message was edited 2 times. Last update was at 30/05/2009 22:05:43
|
SCWCD
SCJP
Pedro Henrique Lobato Sena
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 06/07/2011 15:40:57
|
Joaozava
JavaChild
Membro desde: 13/09/2006 14:09:58
Mensagens: 144
Localização: São Paulo - SP
Offline
|
Olá,
Ressuscitando o post...
Tenho o mesmo problema, cada cliente possui um schema.
Só que não estou usando Seam, mas sim Spring + JPA + JSF.
Alguém sabe como posso fazer algo semelhante?
Obrigado.
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 07/07/2011 05:43:58
|
GraveDigger
JavaEvangelist
![[Avatar]](/images/avatar/3332880692313818482a5a0286608ab6.jpg)
Membro desde: 07/07/2005 13:47:12
Mensagens: 354
Localização: Aracajú
Offline
|
Oi Amigo,
Você testou o que postei no meu comentário anterior?
Att
|
SCWCD
SCJP
Pedro Henrique Lobato Sena
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 07/07/2011 10:21:35
|
Joaozava
JavaChild
Membro desde: 13/09/2006 14:09:58
Mensagens: 144
Localização: São Paulo - SP
Offline
|
Olá Pedro.
Mas não estou usando Seam... estou usando Spring.
Nesse post dá pra ver como está minha configuração.
http://www.guj.com.br/java/246469-spring-jpa-e-varios-schemas-#1277521
Aqui vc disse:
Não se aventure em tentar mudar o schema de uma determinada Session(ou mesmo sessionFactory) em tempo de execução, será um grande desperdício de tempo.
Então seria mais indicado criar vários EntityManagers? Isso não tornaria a aplicação mais pesada?
Obrigado!
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 07/07/2011 10:24:18
|
GraveDigger
JavaEvangelist
![[Avatar]](/images/avatar/3332880692313818482a5a0286608ab6.jpg)
Membro desde: 07/07/2005 13:47:12
Mensagens: 354
Localização: Aracajú
Offline
|
Olá,
Mesmo com Spring a idéia é a mesma.
Quando fiz o meu post estávamos usando Seam agora já migramos para o Spring também, fizemos um refactoring mas a idéia em si é a mesma, só tivermos que adequar as especificidades do Spring.
Infelizmente não posso disponibilizar o código por pertencer a empresa, mas o caminho que seguimos é justamente o que postei anteriormente.
Att
|
SCWCD
SCJP
Pedro Henrique Lobato Sena
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 07/07/2011 10:26:36
|
Joaozava
JavaChild
Membro desde: 13/09/2006 14:09:58
Mensagens: 144
Localização: São Paulo - SP
Offline
|
Ok, obrigado Pedro.
Vou tentar adaptar ao Spring, qq dúvida eu posto aqui
|
|
|
 |
|
|
|
|