| Autor |
Mensagem |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 01/12/2007 15:00:13
|
RafaelVS
JavaEvangelist
![[Avatar]](/images/avatar/50454f95bbf5e6478cc0a55d08338731.jpg)
Membro desde: 13/12/2006 09:50:16
Mensagens: 405
Localização: Recife - PE
Offline
|
Pessoal,
Estou estudando pelo livro Enterprise JavaBeans 3.0 5th Edition de Bill Burke .
Lá diz que ao criar um relacionamento unidirecional um para muitos tem pelo menos 2 possibilidades:
1. na tabela do lado "muitos" colocar uma FK para a tabela do lado 1.
2. criar uma tabela de ligacao com 2 colunas, cada uma sendo FK de cada entidade, sendo que a coluna do lado do "muitos" deve ser AK (pois senao, a relacao seria NxM).
ex. usando linguagem natural pra representar tabelas:
1 Pessoa tem N Enderecos:
1. Pessoa (id), Endereco (id, pessoa_id)
2. Pessoa(id), Endereco(id), Pessoa_Has_Endereco(pessoa_id, endereco_id (unique))
A implementação do Hibernate usa a abordagem 1 e n tive problemas com a mesma.. Só que precisei mudar o AS para GlassFish e, por padrao, ele usa TopLink.. Resolvi usar o TopLink, já que vou implementar a aplicaçao independente de Provedor JPA.
Só que as classes anotadas que estavam funcionando ok com Hibernate, quando mudei para TopLink dava erro... TopLink usa a 2a. abordagem (uso de tabela intermediaria para ligacao). Porem, ele exige que tiremos a annotation @JoinColumn na entidade que mapea uma coluna com @OneToMany.
Classe Pessoa (tambem usando uma linguagem mais simples possivel):
class Pessoa {
@OneToMany
@JoinColumn(name="pessoa_id")
private Collection<Endereco> listaEndereco;
}
Com essa configuracao, o Hibernate gera as tabelas conforme previsto. Porém, usando TopLink, ele diz que não podemos colocar @JoinColumn para relacoes unidirecionais (onde pessoa tem atributo com os enderecos, mas endereco nao tem atributo pessoa). Tudo bem... como o projeto ta pequeno, retirei o @JoinColumn, e o TopLink criou, quase sem problemas, as tabelas conforma a abordagem 2... Porém, ele não colocou endereco_id como chave unica... com isso, a relacao que ele cria, na verdade, é NxM.
Alguém sabe se isso eh um bug conhecido do TopLink? Pesquisei um pouco em um forum da Oracle e o pessoal parece que acha isso comum (mapear relacionamento 1xN nas classes para tabelas NxM eh comum???)
O que acham?
|
- Mestrando em Engenharia de Software no CIn/UFPE;
- Pós-Graduado em Engenharia de Software na POLI/UPE;
- Bacharel em Ciência da Computação na UNICAP (Universidade Católica de Pernambuco);
- Sun Certified Programmer for the Java 2 Platform, Standard Edition 5.0 (score 95%);
- Sun Certified Web Components Developer for J2EE 1.4 Platform (score 89%) |
|
|
 |
|
|
![[Post New]](/templates/default/images/icon_minipost_new.gif) 02/12/2007 23:13:36
|
mertins
Entusiasta Java
Membro desde: 12/05/2007 14:58:58
Mensagens: 18
Offline
|
Olá,
Não entendi o que queres dizer com o uso da aboradagem do toplink.
Uso JPA (a especificação), normalmente com o provedor toplink (tanto no glassfish quanto no oc4j)
e a implementação 1xN é identica a do hibernate, até por que a JPA é que dita as regras e a forma
de fazer. Os providers apenas executam (simialr ao jdbc). Por isto não gosto de fazer nada fora
da implementação.
Por exemplo, as entidades abaixo funcionam vinculadas a apenas duas tabelas (a chave de estado é composta por se tratar de
um sistema já existente). Este código esta operacional usando Toplink em um relacionamento 1xN com duas tabelas apenas.
Espero ter ajudado, ou me desculpa se não entendi direito a dúvida.
This message was edited 1 time. Last update was at 02/12/2007 23:16:00
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 03/12/2007 06:57:52
|
RafaelVS
JavaEvangelist
![[Avatar]](/images/avatar/50454f95bbf5e6478cc0a55d08338731.jpg)
Membro desde: 13/12/2006 09:50:16
Mensagens: 405
Localização: Recife - PE
Offline
|
mertins, obrigado pela resposta...
Ve soh... o problema esta quando o relacionamento entre as classes eh 1xN, mas eh UNIDIRECIONAL, ou seja, no seu exemplo, pra o toplink gerar as tabelas do modo como falei, a classe Pais tinha que ter um atributo Collection<Estado> (como ja tem), soh que Estado NAO PODE ter um atributo Pais. No seu caso, o relacionamento eh 1xN, mas eh BIDIRECIONAL.
Por favor, tenta fazer esse teste (apenas retirar o atributo Pais da classe Estado) e tenta gerar as tabelas pelo toplink. E vc verá que vao ser geradas 3 tabelas, uma para Pais, uma para Estado e uma Pais_Estado (por ex.) com as colunas pais_id e estado_id.
|
- Mestrando em Engenharia de Software no CIn/UFPE;
- Pós-Graduado em Engenharia de Software na POLI/UPE;
- Bacharel em Ciência da Computação na UNICAP (Universidade Católica de Pernambuco);
- Sun Certified Programmer for the Java 2 Platform, Standard Edition 5.0 (score 95%);
- Sun Certified Web Components Developer for J2EE 1.4 Platform (score 89%) |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 03/12/2007 14:45:02
|
mertins
Entusiasta Java
Membro desde: 12/05/2007 14:58:58
Mensagens: 18
Offline
|
Hum, o teu problema é com o relacionamento unidirecional.
Foi mal. Pois é. Eu não uso o Relacionamento 1xN unidirecional por este detalhe da terceira tabela (acho totalmente desnecessário)
e também por vícios do desenvolvimento relacional, onde tudo é bidirecional. A especificação do JPA
diz que este tipo de relacionamento deve implementar uma terceira tabela, bem como tu
descreveu (O item 2.1.8.5.1 da JSR 220 diz isto). A resalva é que deveria ser criada
uma unique key para garantir o 1xN). O que não aconteceu. Pode ser um bug.
Ah, também não crio as tabelas através do mecanismo do JPA, dai este problema nunca me ocorreu.Mas testei
com duas classes no jdeveloper e o toplink do oc4j também não criou a constraint de unique. Dai ficou permitindo NxN.
Não testei dentro do Glashfish.
Parece mesmo um bug, mas não achei nenhuma reclamação explicita sobre isto na net.
Só uma dúvida minha, o Hibernate construiu o relacionamento unidirecional de um para muitos sem usar a terceira tabela?
Apesar de achar isto o mais correto e sensato, vai contra a especificação do JPA. E dai tá errado também.
Mais uma: é provável que JPA 2 suporte Relacionamento 1xN unidirecional com apenas chave estrangeira, sem
a necessidade de join table. Muito melhor.
t+
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 03/12/2007 15:02:39
|
RafaelVS
JavaEvangelist
![[Avatar]](/images/avatar/50454f95bbf5e6478cc0a55d08338731.jpg)
Membro desde: 13/12/2006 09:50:16
Mensagens: 405
Localização: Recife - PE
Offline
|
mertins, foi exatamente isso que aconteceu. Vejo, entao dois problemas aih: 1. Hibernate está implementando contra a especificação, embora esteja fazendo da maneira mais sensata. 2.1. Se a especificação JPA não mencionar que deve haver a restrição única, então a especificação JPA está errada (por transformar o relacionamento 1xN em NxM no banco) e a implementação do Toplink está "corretissima" por estar seguindo a especificação, mas estaria propagando o erro da mesma. 2.2. Se a especificação JPA mencionar a restrição única, então o Toplink está implementando quase como especificado, pois está criando a terceira tabela, mas não está colocando a restrição unique, permitindo relacionamento NxM. Esse seria um caso onde deveriamos notificar um dos responsáveis? t+
This message was edited 1 time. Last update was at 03/12/2007 15:05:01
|
- Mestrando em Engenharia de Software no CIn/UFPE;
- Pós-Graduado em Engenharia de Software na POLI/UPE;
- Bacharel em Ciência da Computação na UNICAP (Universidade Católica de Pernambuco);
- Sun Certified Programmer for the Java 2 Platform, Standard Edition 5.0 (score 95%);
- Sun Certified Web Components Developer for J2EE 1.4 Platform (score 89%) |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 03/12/2007 15:25:58
|
mertins
Entusiasta Java
Membro desde: 12/05/2007 14:58:58
Mensagens: 18
Offline
|
Rafael,
Acho que a especificação tá certa, pois mesmo não ressaltando veemente a necessidade da unique key, no final do item ela afirma
que uma unique key será criada.
O Hibernate tá desrespeitando a especificação. Mas não é um grande crime.
Acho que o correto seria lançar o bug nos canais corretos (sinceramente não sei onde, mas deve ser dentro do glassfish)
Eu continuo criando as bases através de scripts.sql. E os projetos tem de possuir os modelos ER adequados.
t+
This message was edited 1 time. Last update was at 03/12/2007 15:27:25
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 03/12/2007 15:55:58
|
RafaelVS
JavaEvangelist
![[Avatar]](/images/avatar/50454f95bbf5e6478cc0a55d08338731.jpg)
Membro desde: 13/12/2006 09:50:16
Mensagens: 405
Localização: Recife - PE
Offline
|
mertins, eu considero esse erro do hibernate um grande crime pelo fato de que se vc migrar o provider, vai dar pau... tipo se eu tou usando o hibernate, eu vou ter uma FK na tabela do lado do N. Se eu trocar pra Toplink, ele vai assumir que eu tenho a terceira tabela, quando na verdade ela nao existe e aih ja viu a bronca... Sem contar que os mapeamentos sao incompativeis... por ex... se for unidirecional, no hibernate basta colocar @JoinColumn(name="pais_id")... Já no Toplink, nao pode ter @JoinColun... ao inves disso, deve ter a @JoinTable com uma lista de joinColumns e inverseColumns. Ou seja, bagunça total.
This message was edited 1 time. Last update was at 03/12/2007 16:16:33
|
- Mestrando em Engenharia de Software no CIn/UFPE;
- Pós-Graduado em Engenharia de Software na POLI/UPE;
- Bacharel em Ciência da Computação na UNICAP (Universidade Católica de Pernambuco);
- Sun Certified Programmer for the Java 2 Platform, Standard Edition 5.0 (score 95%);
- Sun Certified Web Components Developer for J2EE 1.4 Platform (score 89%) |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 04/12/2007 10:22:31
|
mertins
Entusiasta Java
Membro desde: 12/05/2007 14:58:58
Mensagens: 18
Offline
|
Pois é Rafael. Pensando sobre o assunto cheguei a duas conclusões.
A primeira é que até onde eu ouvi falar o Hibernate responde a especificação JPA, além de permitir a utilização
de recursos extras (toplink também faz isto, e claro que os recursos extras podem ter até similaridades
entre funcionalidades de um e outro, mas a sintaxe é diferente). Assim, deveria o hibernate aceitar a chamada
@OneToMany(), por ser o formato correto da especificação (inclusive ele deveria criar as três tabelas, com pks, fks, e
a famosa unique key). Tu testou este formato no hibernate (não tenho aqui um hibernate para testes, não por hora).
A outra conclusão é que se tu deixa o mecanismo JPA criar as tabelas é por que tu não tá muito interessado
no formato das tabelas, pois o que interessa é o resultado nos objetos Entity. Isto abriria margem (apesar da
especificação não permitir) a escolha pelo mecanismo da forma de implatar o recurso. Tipo, vamos supor que no Oracle
o 1xN unidirecional possui melhor performance com 3 tabelas e no Postgresql a melhor performance é com duas
tabelas (lembrando que isto é pura ficção e delirio). Claro que não seria mais possível trocar o provider de JPA sem
reestruturar a base.
No mais é ver se o hibernate responde a especificação e que pelo menos nos nossos testes o toplink apresentou um
bug na geração das tabelas (mais um motivo pra continuar gerando a base através de scripts )
t+
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 04/12/2007 14:20:47
|
RafaelVS
JavaEvangelist
![[Avatar]](/images/avatar/50454f95bbf5e6478cc0a55d08338731.jpg)
Membro desde: 13/12/2006 09:50:16
Mensagens: 405
Localização: Recife - PE
Offline
|
Bem lembrado.
Acho, então, que o fato de o Hibernate ter gerado feito o relacionamento com 2 tabelas + FK deve ser algo "a mais" que o hibernate oferece. Pois, como falei la no primeiro post, estou comecando a estudar EJB, JPA, etc... e na hora de fazer o mapeamento acabei me desligando da especificacao e fui desenvolvendo apenas na intuicao e nas dicas da IDE... Com isso, passou despercebido o fato de o mapeamento unidirecional ser especificado para ser feito atraves de @JoinTable, ao inves de @JoinColumn... talvez a possibilidade de colocar @JoinColumn seja especifica do hibernate e signifique que, caso vc coloque tal annotation, ele vai gerar o relacionamento apenas com duas tabelas..
Eu realmente nao tentei gerar a tabela com o hibernate sem @JoinColumn... aqui nao tenho como testar isso, mas em casa testarei.
Quanto ao fato de eu ter deixado o mecanismo JPA gerar as tabelas foi pq, como estou estudando essa especificacao, gostaria de ver como eh o comportamento da geracao. Claro que para desenvolver um sistema em producao, eu costumo modelar em uma ferramenta ER e gerar os scripts de criacao.
Depois posto o resultado do teste com hibernate.
|
- Mestrando em Engenharia de Software no CIn/UFPE;
- Pós-Graduado em Engenharia de Software na POLI/UPE;
- Bacharel em Ciência da Computação na UNICAP (Universidade Católica de Pernambuco);
- Sun Certified Programmer for the Java 2 Platform, Standard Edition 5.0 (score 95%);
- Sun Certified Web Components Developer for J2EE 1.4 Platform (score 89%) |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 05/12/2007 18:55:14
|
Cabazzo
JavaChild
![[Avatar]](/images/avatar/7f1b9e870ce469ea8f20e0a89bbc9ef8.jpg)
Membro desde: 06/11/2007 13:58:32
Mensagens: 137
Localização: Recife, PE
Offline
|
Rafael, a puco fiz curso de EJB 3.0 na Qualit, e não conheço muita gente que está programando nesta tecnologia. Já fiz alguns programas aqui na empresa, se quizer podemos trocar idéias sobre esta plataforma.
|
Flex 4.5 ACE Certified. |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 03/01/2008 16:38:07
|
O_SANTO_
Entusiasta Java
![[Avatar]](/images/avatar/676b58765ad419a5b7af6a959d4de341.jpg)
Membro desde: 27/07/2005 16:45:24
Mensagens: 17
Localização: Brasil : Nordeste : Paraíba : João Pessoa
Offline
|
Depois de apanhar tentando não criar esta terceira tabela, desisti.
vejo que isso é uma limitação do JPA e não tem pra onde fugir.
Quem resolver esse problema sem usar um relacionamento BIDIRECIONAL, por favor, responda a este tópico.
|
http://ricardojrm.blogspot.com |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 05/01/2008 10:00:40
|
thiago_santos
Thread.start()
![[Avatar]](/images/avatar/6ae2e6c404abc28406ee88e3ac525aae.jpg)
Membro desde: 28/12/2006 11:02:18
Mensagens: 41
Offline
|
Olá Pessoal... Estou com um problemão no relacionamento 1xN. O sistema que eu estou fazendo tem o entity principal Agent e o entity ContactAgent. O Agent tem uma lista de ContactAgent, no entity do ContactAgent eu quero que apareça o campo AGENTUID(chave primária do entity Agent). Então no sistema quando eu vou salvar o Agent com seus ContactAgent`s ele salva quase tudo certo. No banco os registros são salvos só que o campo AGENTUID na tabela ContactAgent fica nulo. E eu não acho a solução, encontrei bem poucas pessoas com esse problema. Eu uso como banco de dados, o MySql. Vejam os códigos abaixo:
Agent, parte do código onde tem os relacionamentos...
ContactAgent, parte do código onde tem os relacionamentos...
Classe que persist os registros...
Alguém aí já passou por isso?
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 05/01/2008 16:34:59
|
mertins
Entusiasta Java
Membro desde: 12/05/2007 14:58:58
Mensagens: 18
Offline
|
O_SANTO_, não tem jeito, com o relacionamento 1xN(OneToMany) unidirecional a especificação JPA 1.0 (atual) exige a criação da terceira tabela (ruim, mas fazer o que?), ver item 2.1.8.5.1 (pg 32) da especificação JSR-220. Mas o relacionamento Nx1(ManyToOne) permite o uso de duas tabelas, mesmo quando unidirecional (item 2.1.8.3.2).
thiago_santos, tu adicionou itens a List referenciada pela variavel contactAgentList? O comportamento apresentado é a de uma lista vazia. Hum, e como o relacionamento é bidirecional, tem de associar ao outro lado também. No exemplo que coloquei bem no inicio do tópico, eu faço isto pois quando adiciono um Estado a list do Pais, registro o Pais no Estado em questão.
Aumenta o log do TopLink para ver os SQL's gerados. No arquivo persistence.xml, dentro da tag <persistence-unit> coloca o seguinte:
Talvez ajude,
t+
This message was edited 3 times. Last update was at 05/01/2008 17:08:59
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 06/01/2009 10:35:20
|
ricardo.longa
Entusiasta Java
Membro desde: 27/11/2008 15:49:43
Mensagens: 23
Offline
|
thiago_santos, estou com este mesmo problema seu...
Tenho duas tabelas, CD e faixa, onde 1 CD possui 1 ou mais faixas. Caso eu persista uma faixa, automaticamente está sendo persistido o CD, porém, se for o oposto, ao persistir o CD não está sendo persistido as faixas.
Mas estive analisando os códigos do mertins e acho que aí está a solução, ao chegar em casa a noite farei os testes.
Você já fez os testes thiago_santos?
[]'s.
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 11/01/2009 15:23:19
|
ricardo.longa
Entusiasta Java
Membro desde: 27/11/2008 15:49:43
Mensagens: 23
Offline
|
Caramba, não creio que terei que criar uma terceira tabela. Que coisa chata hein!
[]'s.
|
|
|
 |
|
|