Alguém sabe como posso fazer mapeamentos complexos entre tabelas e uma única classe? Por exemplo, como posso mapear cinco tabelas em uma classe java? Estou com um banco de dados legados e não estou conseguindo fazer uma mapeamento desse tipo. As annotations OneToMany, ManyToMany, ManyToOne e SecondaryTable são, aparentemente, insufientes, pois, além do número excessivo de tabelas, algumas das chaves estrangeiras compostas não fazem parte da chave primária nas tabelas alvo, ou ainda, as tabelas estão associadas em cascata, como relacionamentos fracos encadeados entre as tabelas, o que inviabiliza o uso das referidas annotations. Suspeito que a solução seja utilizar annotations específicas do hibernate, mas não sei quais. Talvez @Formula, ou @NamedQuery, mas não sei como mapear toda a classe usando essas anotações.
Gostaria de saber, também, se alguém tem algum material falando sobre as limitações do JPA e como contorná-las. Já andei estudando o tutorial da OpenJPA, mas não foi suficiente.
Não tenho certeza, mas talvez a serialização resolva, nem sei direito o que é serialização, mas parece que ela ajuda a resolver coisa do tipo!!
D
davimcabral
Olá Thiago,
Já havia colocado o serializable, mas não funcionou. Por falar nisso, para que serve mesmo o serializable? Outra coisa, onde devo usá-lo: na classe Entity ou na classe Id?
Voltando a assunto do tópico, estou percebendo que os mapeamentos da JPA exigem esquemas de tabelas pré-definidos. Por exemplo, a annotation SecondaryTable exige um relacionamento fraco entre uma tabela principal e uma outra dependente. Além disso, a chave primária da primeira tabela deve ser uma chave estrangeira na segunda. Se isso não ocorrer, não há como utilizar a annotation. Eu acredito que, para resolver os problemas de mapeamentos complexos entre várias tabelas, a solução esteja em annotations como @SqlResultSetMapping, @EntityResult, @FieldResult, @NamedNativeQuery etc., mas ainda não sei usá-las corretamente. Alguém pode dar uma luz?
D
ddduran
quando o banco é legado, eu recomendo você usar o hibernate tools e não recomendaria você mapear varias tabelas numa mesma classe.
OneToOne não te ajudaria?
em todo caso, se você fizer uma query nativa você pode usar um aliasToBean no seu transform
é só dar aos alias das colunas o mesmo nome que os atributos da sua classe
G
Giulliano
Pô galera desculpa a patada…mas como vcs querem mexer com hibernate e nem sabem o que é serialização…
pelo amor de Deus, hein !!!
Se vcs não sabem o que é serialização imagino que um objeto transiente nem passe pela vossas cabeças…
Serialização é um método de encapsular informações em um pacote a fim de transmiti-los por meios externos por exemplo um pojo
Transiente são os membros os quais vc não desejaria que fosse passado na serialização…
boa sorte
D
ddduran
é pessoal, só agora vi as respostas de vocês, embora o Giulliano tenha sido um pouco severo ele tem razão
um objeto ser serializavel indica que ele pode ser transformado em em um “array binario” para ser, por exemplo, gravado em arquivos de texto ou transmitido pela rede e depois serem recuperado o seu estado original.
quando você implementa a interface Serializable você está indicando que objetos dessa classe podem ser serializados
Pô galera desculpa a patada…mas como vcs querem mexer com hibernate e nem sabem o que é serialização…
pelo amor de Deus, hein !!!
Se vcs não sabem o que é serialização imagino que um objeto transiente nem passe pela vossas cabeças…
Serialização é um método de encapsular informações em um pacote a fim de transmiti-los por meios externos por exemplo um pojo
Transiente são os membros os quais vc não desejaria que fosse passado na serialização…
boa sorte
Olá Giulliano,
Sei para que serve a interface serializable em java, inclusive o enum do java5 veio para solucionar um problema que não era resolvido com constantes e serializable. A questão principal aqui é sobre mapeamento em tabelas complexas usando JPA. Quando você não persiste o objeto no sistema de arquivos ou transmite-o através da rede, não sei se o conceito de serializable ajudaria ou atrapalharia muito. Acho que o fato de saber ou não se a interface serializable fica na classe entity ou na classe id não iria resolver a questão levantada por esse tópico, nem irá ajudá-lo a declarar, em JPA, por exemplo, uma classe entity com uma chave composta, sendo uma das suas chave componente uma outra classe. Já fiz isso com um banco legado e não é algo muito intuitivo na JPA, mesmo já lido várias documentações. Já consegui fazer mapeamentos ManyToOne, OneToMany, OneToOne, SecondaryTable etc., usando chaves compostas, mas nem sempre o JPA funciona como o esperado. Uma coisa é deixar que as tabelas sejam criadas a partir do mapeamento, outra coisa é mapear as classes a um conjunto de tabelas legadas. Além disso, a finalidade de JPA deveria ser facilitar a vida do programador e diminuir o número de linhas de código. O ideal seria que pudéssemos modelar uma camada de negócios independente da forma como ela será armazenada e fazer o mapeamento, de maneira a isolar as camadas. Caso contrário o melhor usar DAO puro, pois a produtividade acaba sendo maior.
G
Giulliano
davimcabral
Na minha opnião a solução para o seu caso seria o hibernate tolls, não acho que vc mapeando um banco legado na mão vá acolher todos os principos da JPA.
Eu precisei refazer uma aplicação aqui no meu serviço e nunca havia usado essa ferramenta, aprendi rapidamente, mesmo pq ela é muito intuitiva e ela fez todo o mapeamento para mim…
e ae se vc achar q não deve usar a ferramenta…faz em um projeto separado só pra ver como ele fez e quem sabe vc ganha umas idéias…
I
Ironlynx
Giuliano, pergunta de quem é newbie em Hibernate: E ele(o Tools) permite assim lidar(leia-se migrar, ou refazer) com bases de dados legadas(leia-se antiquíssimas)???Se eu tiver uma app usando Visual Fox Pro, e quero passá-la para MySQL ele me dá suporte a isso???
D
davimcabral
Você conhece algum plugin desses para o eclipse? Sabe de algum tutorial de como configurar a ferramenta? Já tentei usar o plugin Dali. Configurei a conexão com o banco e testei-a, mas o plugin não conseguiu visualizar as tabelas. Acho que pode ser algum problema de configuração do pugin.
D
ddduran
o HT geralmente só faz engenharia reversa pega o se script de banco e converte ele em modelagem de classe, mas você pode pegar essa modelagem do Visual Fox Pro, reconfigurar seu hbm para conectar no MySql, ai o Hibernate tem um recurso que cria a base de dados baseada na modelagem de classe.
assim:
Configuration cfg = new AnnotationConfiguration();
cfg.configure();
SchemaExport se = new SchemaExport(cfg);
se.create(true, true);
só que a engenharia reversa e o SchemaExport só funcionam bem se a base tiver bem modelada.
mas da uma olhada nele o HT é um excelente plugin
D
davimcabral
É isso que tenho percebido: nem sempre em JPA é possível fazer uma camada de negócios independente da camada de persistência, pois muitos dos mapeamentos padrão da JPA esperam encontrar certos e determinados esquemas de relacionamento entre tabelas no banco de dados. Isso quebra um pouco a idéia de divisão em camadas e da independência entre essas camadas. Suponhamos que você tenha um sistema todo feito, com camadas de apresentação, de negócio e de persistência. Aí o DBA da sua empresa faz um refatoramento no banco, ou então a necessidade de um outro sistema acaba exigindo esse novo refatoramento. Caso esse refatoramento não se enquadre perfeitamento nos esquemas de mapeamento pré-fabricados da JPA, você terá que fazer modificações desde a camada de persistência (isto é, as annotations nas classes de domínio do problema), até a camada de apresentação, passando também pela de negócio. Por isso a minha preocupação em saber se há alguma maneira de fazer mapeamentos complexos sem as annotations básicas cmo MayToOne, OneToMany, ManyToMany e OneToOne. Tentei fazer alguns testes com @SqlResultSetMapping, @EntityResult, @FieldResult e @NamedNativeQuery, mas ainda não obtive sucesso.
Com relação a dúvida de ddduran, nunca testei isso, mas parece fazer sentido. Nesse caso você teria dois arquivos xml de mapeamento para os DBs legados, um para importar os dados de um dos DB e outro para exportá-los para o outro DB? Bastante interessante esse seu questionamento.
D
ddduran
Hum, deixa eu ver se entendi direito
bom é um banco relacional, ter relações bem definidas entre tabelas é o minimo, ne?
nem sempre em JPA é possível fazer uma camada de negócios independente da camada de persistência
hum você ainda pode fazer classes de mapeamento entre elas, expor o minimo dos seus objetos com interfaces, etc, mas será mesmo necessario?
bom acho que essa situação ia impactar em refatoração de qualquer jeito com ou sem JPA. o bom é que com o HT você refaria sua camada de persistencia em dois cliques :), sem ele, a JPA e uma Solução ORM, la ia você alterar 823748937284 querys em DAOs.
A duvida não era minha eu dei uma resposta. Eu já teste funciona, você teria um só configure com o banco que você quer, é só que ia fazer a do banco legado primeiro pra gerar os Entitys ai depois alterar ele para o banco novo e executar (uma unica vez) o SchemaExport.
uma das vantagens do hibernate é poder trocar de banco sem muitos traumas.
D
davimcabral
Concordo com você em alguns pontos, mas descordo em outros.
ddduran:
Hum, deixa eu ver se entendi direito
bom é um banco relacional, ter relações bem definidas entre tabelas é o minimo, ne?
Isso se você pode garantir que os que trabalharam antes de você fizeram um bom trabalho. Caso contrário…
ddduran:
Realmente com JPA isso fica burocrático.
Não impacta não. Já desenvolvi um sistema que se comunicava com dois bancos de dados distintos. Esse sistema usava DAO e era dividido em 3 camadas. Quando houve modificações no esquema do banco de dados, só precisei refazer parte do mapeamento em uma das camadas de persistência, não afetando em nada na camada de negócios nem na de apresentação.
Como vc poderia fazer um sistema fazer os dois caminhos, ou seja, exportar de um banco de dados para outro e importar de volta?
Mais ou menos qndo trabalhamos com banco de dados legado.
A minha preocupação maior é delimitar bem quando usar JPA. Acredito q somente qndo eu não possuir um banco de dados legado ou qndo for trabalhar com este mas sem a preocupação de criar uma camada de negócios reutilizável em um grande sistema. Não consigo ainda visualizar a crição de uma camada de negócio, que realmente isole a camada de apresentação da de persistencia, de maneira a poder se utilizada por vários desenvolvedores. Esse é o problema que me levou a abrir esse tópico.
D
ddduran
Assim, claro há uma solução para cada problema, mas JPA é um excelente framework para muitos casos , não para todos.
Como vc poderia fazer um sistema fazer os dois caminhos, ou seja, exportar de um banco de dados para outro e importar de volta?
pow, do jeito que eu falei, assim:
configure o hibernate tools para seu banco legado
mande ele gerar as classes de dominio com JPA
configure seu hibernate.cfg.xml para o banco que você vai usar
escreva uma classe com o metodo main e o codigo que passei acima