Estou fazendo um sistema em que em alguns casos vou precisar me comunicar com bases legadas. por exemplo, o sistema de usuario deve ser acoplavel a algum ja existente, seja ldap, sap ou uma tabela do banco de dados que a empresa tenha login/senha. Ateh ai uma interface para o DAO do User resolve.
Mas como fica para eu fazer relacoes? Isto eh, se uma classe minha tem uma relacao com User, na hora que eu persistir essa classe, como vou fazer uma foreign key para User? Claro, posso usar a PK do User legado, mas se a outra classe eu estiver usando hibernate, vai ser uma bela meleca.
Seria entao melhor que a classe que eh relacionada a User ter uma referencia a um ipo UserProxy, e esse sim seria sempre hibernetado e teria um metodo getRealUser nele, que me devolve um User, e esse UserProxy (po, que nome ruim) faria o select ou chamada ao LDAP/SAP e populava um objeto da interface User pra mim?
pra piorar: nao soh o User pode ser puxado de base legada, pode ser que Cliente e Fornecedor e mais um monte de outras classes precisem ser puxadas da base legada. Agora imagine o pior caso: eles ja tem tabelas de User, Cliente e Fornecedor, soh que as tabelas deles nao possuem os dados suficientes que eu preciso, ou possuem mais. O que eu faco?
Eh melhor uma solucao que sincroniza a base do meu sistema com o legado deles toda a noite por XML? Qual a experiencia de voces?
toda opiniao, e em especial experiencias, sao muito bem vindas. muito obrigado
Você tem um sistema que pode ao mesmo tempo ter várias bases ou pode ser instalado com diversas bases?
O que você vai precisar, de qualquer jeito, é um conjunto de classes responsáveis por Mapear seu domínio de aplicação para a tecnologia de persistência.
Eu tenho o caso específico de uma base SQL e uma base legada num banco proprietario.
eu tenho um software de caixinha que muitas vezes vai rpecisar de customizacoes, eu ja quero deixar isso da melhor maneira possivel. ele pode rodar de maneira standalone ou algumas entidades podem ser puxadas da base legada. O problema eh que vou ter relacionamentos com essas entidades.
shoes, detalhe melhor a sua solucao. voce tem uma classe que a instancia dela explica como eh mapeada tal classe? snippets?
Eu estou quase nessa situação atualmente num projeto pessoal.
O relacionamento em si quem vai ter que garantir é a sua aplicação, então basta você ter um identificador para cada instância e usar este identificador nas diversas tabelas.
Você pode associar cada classe com um DAO (um DataMapper). Este DAO é obtido por uma Factory ou injeção de dependências.
Quando um DAO persiste um atributo, ele usa os outros DAOs para fazer os serviçoes de persistir associações, por exemplo:
class UsuarioDaoJdbc{
public salvar(Usuario u){
String sql="INSERT INTO BLABLABLA () VALUES(?,?...");
PreparedStatement st = ...
st.setString(1, u.getLogin());
st.setString(2, u.getNome());
EmpresaDao empresaDao =DaoFactory.create(DaoFactory.EMPRESA);//por favor use IoC :P
empresaDao.salvar(u.getEmpresa());
}
}
Dessa forma se o DaoEmpresa for um DAO para LDAP, ele vai saber como salvar a empresa lá.
Mantenha a inteligência sobre onde persistir nos DAOs, não deixe seus objetos de domínio saber sobre onde eles vem.
o problema eh se o dao da empresa usar Hibernate. e se Empresa eh uma classe persistente, ela nao pode ter um relacionamento com sua classe Usuario, ja que ela nao seria hibernate-persistente.
Meu problema eh misturar classes hibernate com nao hibernate, sendo que as duas eu vou persistir e manter relacoes entre elas. e fazer isso de tal maneira que as vezes soh haverao classes hibernate, as vezes vou ter de puxar de bases legadas/
Para mim o mais fácil é a solução de replicação de dados entre as bases feita a noite ou em algum horário apropriado às regras do negócio.
Mas a solução do Shoes parece interessante e mais atual. Achei no google o pdf (que não li) Execution of Data Mappers com o seguinte Abstract:
Data mappers são operadores essenciais para implementar transformação de dados suportando mapeamentos de schema e cenários de integração tais como migração de dados legados, processos ETL (extract, transform and load) para data warehousing, atividades de data cleaning (detecção e correção de erros) e iniciativas de integração de negócios.
Este artigo propõe um Data mapper como uma extensão da algebra relacional e fornece uma série de regras para otimizar queries que combinam operadores relacionais padrões com Data mappers.
o maior problema disto são as queries …
fazer os objetos se comportarem desta maneira, ´pe fácil com um pouquinho de AOP (por exemplo, colocar um interceptor em getUser e em setUser para fazer a mágica )
a parte de autenticação só iria complicar se você precisar usar SSO, ai tem que deixar a autenticação externa ao sistema.
fazer via sincronização não é uma opção para este caso?? acho que seria a maneira mais fácil, tipo deixar duas vezes por dia um importador de base rodando para o sistema destino
se sincronização não for uma opção, da pra usar CustomTypes do hibernate que iriam mapear o load/save do objeto relacionado com o teu backend de persistencia real do objeto.
mas esta solução faz tu perder toda a possibilidade de aninhamento de propriedades nas queries, mas mesmo assim acho que é a de mais fácil implementação, ou é isto ou então AOP mesmo, com interceptação de get/set ou então de campos mesmo e um pouquinho de introduction de campos novos na classe para armazenar o valor real persistido do objeto
Você não vai conseguir usar todos os recursos de uma ferramenta neste modelo louco
Acho que seu DAO vai ter que saber trazer apenas o objeto, sem associacao (o que pode ser uma bela porcaria, visto que voce vai ficar limitado no mapeamento…vai ter que cair no velho uma-classe-para-uma-tabela quase sempre).
Alguém antes do DAO vai ter que saber montar o objeto vindo das diversas fontes, re-montar os relacionamentos. Esse cara vai ter que ser personalizavel por ambiente que o sistema se adapte.
class UsuarioRepository{
public Usuario procurarPorLogin(String login){
Usuario u = daousuario.prucurarPorLogin(login);
Emrpesa xyz = daoEmrpesa.procuraPorUsuario(u);
u.setEmpresa(xyz);
return u;
}
}
Os dados das bases legadas seriam ready only, isso eh, meu sistema nunca vai atualiza-los. Entao parece que o interessante vai ser realmente um esquema de sincronizacao…
Mas ai na hora do save eu tambem preciso itnerceptar para ele colocar a chave relacionada correta… voce tem snippets do seu interceptor que possa publicar?
Com interceptor acredito que tu consegue fazer sem grandes problemas. Vou ver se posso liberar pedaco dos fontes que tenho, mas nao garanto pois foi feito especialmente pra um cliente.
Outra coisa, se fosse hoje usando Hib3 eu nao usaria o Interceptor e faria com os atuais EventListener. Nao sei se tu ja deu uma olhada nessa feature nova do Hib, senao, de uma olhada nas interfaces LoadEventListener e SaveOrUpdateEventListener, tem umas classes default ja implementadas que podem te ajudar.
Bom outra fonte de documentacao é o proprio blog do pessoal do Hibernate, foi por la que eu dei uma estudada nesses carinhas.
O hibernate te permite fornecer classes que implementam a persistencia das tuas classes, usei isso a uns 2 anos para importar dados de uma base legado não-relacional.
Se lembro bem o Hibernate te da uma maneira de fazer o loading de relaciomamentos pra ele assim como CRUD de objetos.
Você perde todo poder de fazer queries nos atributos das custom classes, mas com o 3.0 e muita boa vontade da para resolver isso.
Nao cheguei a ler a thread toda - foi mal, Paulo, mas qualquer mencao a DAOs ja ta me fazendo ficar vesgo. Como ninguem mencionou o iBatis ate agora, achei que valia a pena. Pra casos onde mapear tabelas em formatos bizarros eh mais importante do que a transparencia e magica que o Hibernate faz, eh uma otima:
ja consegui achar direcoes, apesar de que talvez eu fique com sincronizacao, usando o hibernate posso customizar em casos emergenciais sem ter de itnerfacear muitas coisas estranhas.
[quote=cv]Nao cheguei a ler a thread toda - foi mal, Paulo, mas qualquer mencao a DAOs ja ta me fazendo ficar vesgo. Como ninguem mencionou o iBatis ate agora, achei que valia a pena. Pra casos onde mapear tabelas em formatos bizarros eh mais importante do que a transparencia e magica que o Hibernate faz, eh uma otima:
O hibernate parece ter um CustomPersister para vc controlar como será feito a persistencia.
Tem um exemplo com hashtable. Eu acho que ele faz o relacionamento automático das classes.