Como criar ralacionamentos many-to-many sem Hibernate [RESOLVIDO]

9 respostas
humberto-adm

Olá galera,

Eu vou começar a desenvolver uma aplicação e no meu banco de dados tenho tabelas com relacionamentos one-to-many, many-to-many.
A dúvida é a seguinte, em relação ao relacionamento one-to-many, eu sei implementar, agora em relação ao many-to-many eu tenhos dúvidas.

Qual é a melhor forma de se implementar uma situação dessa?
O que seria many-to-many sem classe associativa?
O que seria many-to-many com classe associativa?

Gostaria de ver alguns exemplos para entender melhor essas situações.

Obs: Não vou usar Hibernate.

Obrigado pessoal.

9 Respostas

jsign

Olá Humberto,
Recentemente precisei rever um pouco meus conceitos de relacionamentos, justamente por estar criando uma aplicação de teste com hibernate.
Como para o Hibernate, relacionamentos N x N são tratados com tabelas associativas, acredito que esta seja a melhor prática.

Na verdade não consigo imaginar um relacionamento de muitos para muitos sem uma tabela relacional entre as entidades.

Veja:

Um carro cabe muitas pessoas.
Muitas pessoas cabem em muitos, diferentes, carros.
Assim:

pessoa ------------------ carro
1 --------------------------- 1
2 --------------------------- 2
3 --------------------------- 3
4 --------------------------- 4
4 --------------------------- 1
3 --------------------------- 2
2 --------------------------- 3
1 --------------------------- 4
4 --------------------------- 2
3 --------------------------- 1
2 --------------------------- 4
1 --------------------------- 3

A pessoa 1, por exemplo, é passível passageira dos carros 1, 4 e 2.
O carro 1, por exemplo, é passível transporte das pessoas 1, 4 e 3.

Podemos chamar esta tabela que vincula estes relacionamentos de pessoa_carro, e é assim que o hibernate irá criar.
No seu caso, como não irá utilizar este framework, sugiro que crie as tabelas pessoa, carro e pessoa_carro.
Criando as devidas chavez estrangeiras nesta ultima (pessoa_carro), quais seria, por exemplo, pessoa_id e carro_id.
Tem um exemplo de como colocar na prática esta situação com uso do Hibernate. http://www.guj.com.br/posts/list/218131.java#1114315

Pensando agora como seria sem esta tabela associativa:

Tabela carro / campos:
------- id ------------
------- marca --------
------- modelo -------
------- pessoa_id ----

Tabela pessoa / campos:
------- id ------------
------- nome ---------
------- cpf -----------
------- carro_id ------

O que aconteceria, teriamos de repetir o cadastro de carro ou de pessoas.

exemplo da tabela de carros populada:

Tabela carro / campos:

------- id ------------ 1
------- marca -------- chev
------- modelo ------- classic
------- pessoa_id ---- 1

------- id ------------ 2
------- marca -------- chev
------- modelo ------- classic
------- pessoa_id ---- 2

------- id ------------ 3
------- marca -------- chev
------- modelo ------- classic
------- pessoa_id ---- 3

ou repetir na de pessoas:

Tabela pessoa / campos:

------- id ------------ 1
------- nome --------- Fulano
------- cpf ----------- 123123123
------- carro_id ------ 1

------- id ------------ 2
------- nome --------- Fulano
------- cpf ----------- 123123123
------- carro_id ------ 2

------- id ------------ 3
------- nome --------- Fulano
------- cpf ----------- 123123123
------- carro_id ------ 3

O indicado é usar uma tabela associativa neste caso (N x N).

Bom, espero ter ajudado.
Boa sorte, se precisar manda i.
Abraços

Jsign

humberto-adm

jsign:
Olá Humberto,
Recentemente precisei rever um pouco meus conceitos de relacionamentos, justamente por estar criando uma aplicação de teste com hibernate.
Como para o Hibernate, relacionamentos N x N são tratados com tabelas associativas, acredito que esta seja a melhor prática.

Na verdade não consigo imaginar um relacionamento de muitos para muitos sem uma tabela relacional entre as entidades.

Veja:

Um carro cabe muitas pessoas.
Muitas pessoas cabem em muitos, diferentes, carros.
Assim:

pessoa ------------------ carro
1 --------------------------- 1
2 --------------------------- 2
3 --------------------------- 3
4 --------------------------- 4
4 --------------------------- 1
3 --------------------------- 2
2 --------------------------- 3
1 --------------------------- 4
4 --------------------------- 2
3 --------------------------- 1
2 --------------------------- 4
1 --------------------------- 3

A pessoa 1, por exemplo, é passível passageira dos carros 1, 4 e 2.
O carro 1, por exemplo, é passível transporte das pessoas 1, 4 e 3.

Podemos chamar esta tabela que vincula estes relacionamentos de pessoa_carro, e é assim que o hibernate irá criar.
No seu caso, como não irá utilizar este framework, sugiro que crie as tabelas pessoa, carro e pessoa_carro.
Criando as devidas chavez estrangeiras nesta ultima (pessoa_carro), quais seria, por exemplo, pessoa_id e carro_id.
Tem um exemplo de como colocar na prática esta situação com uso do Hibernate. http://www.guj.com.br/posts/list/218131.java#1114315

Pensando agora como seria sem esta tabela associativa:

Tabela carro / campos:
------- id ------------
------- marca --------
------- modelo -------
------- pessoa_id ----

Tabela pessoa / campos:
------- id ------------
------- nome ---------
------- cpf -----------
------- carro_id ------

O que aconteceria, teriamos de repetir o cadastro de carro ou de pessoas.

exemplo da tabela de carros populada:

Tabela carro / campos:

------- id ------------ 1
------- marca -------- chev
------- modelo ------- classic
------- pessoa_id ---- 1

------- id ------------ 2
------- marca -------- chev
------- modelo ------- classic
------- pessoa_id ---- 2

------- id ------------ 3
------- marca -------- chev
------- modelo ------- classic
------- pessoa_id ---- 3

ou repetir na de pessoas:

Tabela pessoa / campos:

------- id ------------ 1
------- nome --------- Fulano
------- cpf ----------- 123123123
------- carro_id ------ 1

------- id ------------ 2
------- nome --------- Fulano
------- cpf ----------- 123123123
------- carro_id ------ 2

------- id ------------ 3
------- nome --------- Fulano
------- cpf ----------- 123123123
------- carro_id ------ 3

O indicado é usar uma tabela associativa neste caso (N x N).

Bom, espero ter ajudado.
Boa sorte, se precisar manda i.
Abraços

Jsign

Olá Jsign obrigado pela explicação.

Eu andei vendo com um professor e ele indicou criar uma coleção de cada lado, por exemplo, um coleção de pessoas na classe carros e uma coleção de carros na classe pessoa.

Você já trabalhou com esse tipo de implementação?

jsign

Ola Humberto, obrigado e desculpe a demora na resposta,
No link que te enviei tem isso, veja que na classe pessoa tenho um list de endereços e na classe endereços tenho um list de pessoas.
Um list nada mais é que uma collecion ordenada (http://www.devmedia.com.br/post-3162-Utilizando-Collections-Parte-I.html).

Pessoa

@ManyToMany(fetch = FetchType.LAZY)  
     @Cascade(CascadeType.SAVE_UPDATE)  
     @JoinColumn(name="endereco_id")  
    private List<Endereco> endereco;

Endereco

@ManyToMany(targetEntity=Pessoa.class, fetch = FetchType.LAZY)  
     @Cascade(CascadeType.MERGE)  
     @JoinTable(  
                name="pessoa_endereco",  
                 joinColumns=@JoinColumn(name="endereco_id"),  
                 inverseJoinColumns=@JoinColumn(name="pessoa_id")  
                 )  
     private List<Pessoa> pessoa;

Abraços, até mais.

humberto-adm

jsign:
Ola Humberto, obrigado e desculpe a demora na resposta,
No link que te enviei tem isso, veja que na classe pessoa tenho um list de endereços e na classe endereços tenho um list de pessoas.
Um list nada mais é que uma collecion ordenada (http://www.devmedia.com.br/post-3162-Utilizando-Collections-Parte-I.html).

Pessoa

@ManyToMany(fetch = FetchType.LAZY)  
     @Cascade(CascadeType.SAVE_UPDATE)  
     @JoinColumn(name="endereco_id")  
    private List<Endereco> endereco;

Endereco

@ManyToMany(targetEntity=Pessoa.class, fetch = FetchType.LAZY)  
     @Cascade(CascadeType.MERGE)  
     @JoinTable(  
                name="pessoa_endereco",  
                 joinColumns=@JoinColumn(name="endereco_id"),  
                 inverseJoinColumns=@JoinColumn(name="pessoa_id")  
                 )  
     private List<Pessoa> pessoa;

Abraços, até mais.

Me parece que esta explicação é para quando se usa o hibernate e esse não meu caso, eu gostaria de implementar isso na “mão”

Obrigado

jsign

Olá Humberto,
A lógica é a mesma. Conforme especificado no exemplo com hibernate. Você tem uma lista de pessoas em enderecos e uma lista de endereços em pessoas.
No seu caso vai precisar efetuar as consultas em sql.
Sugiro que o faça dentro de uma DAO, esta é a model correta para consultas, não é recomendado ter consultas encapsuldas em objetos do tipo bean.


Espero ter, de alguma forma te ajudado.
Abraços.
Jsign

humberto-adm

Ajudou sim Jsign, agora eu compreendi, vou ler estes tópicos também, obrigado.

jsign:
Olá Humberto,
A lógica é a mesma. Conforme especificado no exemplo com hibernate. Você tem uma lista de pessoas em enderecos e uma lista de endereços em pessoas.
No seu caso vai precisar efetuar as consultas em sql.
Sugiro que o faça dentro de uma DAO, esta é a model correta para consultas, não é recomendado ter consultas encapsuldas em objetos do tipo bean.


Espero ter, de alguma forma te ajudado.
Abraços.
Jsign

Javac

Olá… este é um dos poucos exemplos de N:M q n usam Classe associativa.

Poderiam m mostrar como será na hora de construir o DAO? Como vou gravar no banco já q lá tnho uma tabela associativa; e como faço consulta?

vlw !

humberto-adm

Bom como exemplo imagine um aluno que cursa várias disciplinas e estas disciplinas são cursadas por vários alunos, assim temos um exemplo N:M.

No DAO do aluno você vai ter um método insert na tabela aluno_estuda_disciplina, mas como pode vir várias disciplinas em uma lista, então neste método você usa o for, assim você consegue adicionar todas as disciplinas que o aluno estuda.

Na hora de realizar uma consulta, no DAO do aluno você cria um método que retorna uma lista de todas as disciplinas que o aluno estuda através do seu código, vindas da tabela aluno_estuda_disciplina. Como resultado você terá uma lista com o código de todas as disciplinas que o aluno estuda.

Eu já tive várias dúvidas em relação a este assunto, mas espero ter ajudado, e se precisar estou a disposição.

Abraço.

Javac

Olá! Mt obrigada!, mas eu gostaria muito de saber se existe isso com JPA, pq só vejo saída com SQL Nativo… :frowning:

Criado 11 de setembro de 2010
Ultima resposta 8 de dez. de 2010
Respostas 9
Participantes 3