Ok, então essa é provavelmente uma pergunta trivial, mas estou tendo problemas para visualizar e entender as diferenças e quando usar cada uma. Também sou um pouco incerto sobre como conceitos como mapeamentos unidirecionais e bidirecionais afetam os relacionamentos um para muitos / muitos para muitos. Estou usando o Hibernate agora, então qualquer explicação relacionada ao ORM será útil.
Como exemplo, digamos que tenho a seguinte configuração:
public class Person{
private Long personId;
private Set<Skill> skills;
//Getters and setters
}
public class Skill{
private Long skillId;
private String skillName;
//Getters and setters
}
Então, nesse caso, que tipo de mapeamento eu teria? As respostas a este exemplo específico são definitivamente apreciadas, mas eu também gostaria de ter uma visão geral de quando usar um para muitos e muitos para muitos e quando usar uma tabela de junção versus uma coluna de junção e unidirecional versus bidirecional.
fonte
Respostas:
Um para muitos : uma pessoa tem muitas habilidades, uma habilidade não é reutilizada entre as pessoas
Muitos para muitos : uma pessoa tem muitas habilidades, uma habilidade é reutilizada entre as pessoas
Em um relacionamento um para muitos, um objeto é o "pai" e o outro é o "filho". O pai controla a existência do filho. Em muitos para muitos, a existência de qualquer tipo depende de algo fora dos dois (no contexto maior do aplicativo).
O assunto (domínio) deve determinar se o relacionamento é ou não um para muitos ou muitos para muitos - no entanto, acho que tornar o relacionamento unidirecional ou bidirecional é uma decisão de engenharia que troca memória, processamento, desempenho etc.
O que pode ser confuso é que um relacionamento bidirecional muitos-para-muitos não precisa ser simétrico! Ou seja, várias pessoas podem apontar para uma habilidade, mas a habilidade não precisa se relacionar apenas com essas pessoas. Normalmente, mas essa simetria não é um requisito. Pegue o amor, por exemplo - é bidirecional ("Eu amo", "Me ama"), mas geralmente assimétrico ("Eu a amo, mas ela não me ama")!
Todos estes são bem suportados pelo Hibernate e JPA. Lembre-se de que o Hibernate ou qualquer outro ORM não se preocupa em manter a simetria ao gerenciar relacionamentos bidirecionais de muitos para muitos ... tudo depende do aplicativo.
fonte
Looks como todo mundo está respondendo
One-to-many
vs.Many-to-many
:A diferença entre
One-to-many
,Many-to-one
eMany-to-Many
é:One-to-many
vsMany-to-one
é uma questão de perspectiva .Unidirectional
vsBidirectional
não afetará o mapeamento, mas fará diferença em como você pode acessar seus dados.Many-to-one
domany
lado manterá referência doone
lado. Um bom exemplo é "Um Estado tem Cidades". Nesse caso,State
é o lado único eCity
o lado múltiplo. Haverá uma colunastate_id
na tabelacities
.One-to-Many
um lado, será o nosso ponto de referência. Por exemplo, "Um usuário tem um endereço". Neste caso, pode ter três colunasaddress_1_id
,address_2_id
eaddress_3_id
ou um olhar para cima da tabela com restrição exclusiva emuser_id
eaddress_id
.Many-to-Many
membros de cada parte, pode-se manter referência ao número arbitrário de membros da outra parte. Para isso, é utilizada uma tabela de consulta . Exemplo disso é a relação entre médicos e pacientes. Um médico pode ter muitos pacientes e vice-versa.fonte
s.persons
, como só existes.person
One-to-many
relacionamento que você descreve é umMany-to-many
relacionamento, porqueperson
tem uma referência a muitos,skills
masskill
não mantém referência a uma pessoa em particular e muitospersons
podem ter a mesma referênciaskill
. E seuMany-to-one
relacionamento é realmenteOne-to-many
porque cada habilidade tem uma referência apenas a umaperson
quando a criança tem apenas uma mãe.skills
temperson_id
), você o chama de Um para muitos, mas quando está no lado "Muitos" (usuários e endereços,users
temaddress_id
), então você o chama de Muitos para um. Mas, estruturalmente, os dois casos são idênticos e chamados de um para muitos.1) Os círculos são Entidades / POJOs / Feijões
2) deg é uma abreviação de degree como nos gráficos (número de arestas)
PK = Chave primária, FK = Chave estrangeira
Observe a contradição entre o grau e o nome do lado. Muitos correspondem ao grau = 1, enquanto Um corresponde ao grau> 1.
fonte
Dê uma olhada neste artigo: Mapeando Relacionamentos de Objetos
fonte
this occurs when the maximum of one multiplicity is one and the other is greater than one
lolwut?Um para muitos
O relacionamento de uma para muitas tabelas é o seguinte:
Em um sistema de banco de dados relacional, um relacionamento de tabela um para muitos vincula duas tabelas com base em uma
Foreign Key
coluna no filho que faz referência àPrimary Key
linha da tabela pai.No diagrama da tabela acima, a
post_id
coluna dapost_comment
tabela possui umForeign Key
relacionamento com a coluna dopost
ID da tabelaPrimary Key
:Anotação @ManyToOne
A melhor maneira de mapear o relacionamento de uma para muitas tabelas é usar a
@ManyToOne
anotação.No nosso caso, a entidade filha
PostComment
mapeia apost_id
coluna Chave estrangeira usando a@ManyToOne
anotação:Usando a
@OneToMany
anotação JPASó porque você tem a opção de usar a
@OneToMany
anotação, isso não significa que essa deve ser a opção padrão para todo relacionamento de banco de dados um para muitos . O problema com as coleções é que só podemos usá-las quando o número de registros filhos é bastante limitado.A melhor maneira de mapear uma
@OneToMany
associação é confiar no@ManyToOne
lado para propagar todas as alterações de estado da entidade:A entidade pai
Post
, apresenta dois métodos utilitários (por exemplo,addComment
eremoveComment
) que são usados para sincronizar os dois lados da associação bidirecional. Você deve sempre fornecer esses métodos sempre que estiver trabalhando com uma associação bidirecional, pois, caso contrário, corre o risco de problemas de propagação de estado muito sutis .A
@OneToMany
associação unidirecional deve ser evitada, pois é menos eficiente do que o uso@ManyToOne
ou a@OneToMany
associação bidirecional .Um a um
O relacionamento da tabela um para um é o seguinte:
Em um sistema de banco de dados relacional, um relacionamento de tabela um para um vincula duas tabelas com base em uma
Primary Key
coluna no filho, que também é umaForeign Key
referência àPrimary Key
linha da tabela pai.Portanto, podemos dizer que a tabela filho compartilha
Primary Key
com a tabela pai.No diagrama da tabela acima, a
id
coluna napost_details
tabela também possui umForeign Key
relacionamento com a coluna dapost
tabelaid
Primary Key
:Usando o JPA
@OneToOne
com@MapsId
anotaçõesA melhor maneira de mapear um
@OneToOne
relacionamento é usar@MapsId
. Dessa forma, você nem precisa de uma associação bidirecional, pois sempre pode buscar aPostDetails
entidade usando o métodoPost
identificador entidade.O mapeamento fica assim:
[code language = "java"] @Entity (name = "PostDetails") @Table (name = "post_details") classe pública PostDetails {
} [/ código]
Dessa forma, a
id
propriedade serve como Chave Primária e Chave Externa. Você notará que a@Id
coluna não usa mais uma@GeneratedValue
anotação, pois o identificador é preenchido com o identificador dapost
associação.Muitos para muitos
O relacionamento de tabela muitos para muitos é o seguinte:
Em um sistema de banco de dados relacional, um relacionamento de tabela muitos para muitos vincula duas tabelas pai por meio de uma tabela filha que contém duas
Foreign Key
colunas referenciando asPrimary Key
colunas das duas tabelas pai.No diagrama da tabela acima, a
post_id
coluna dapost_tag
tabela também possui umForeign Key
relacionamento com a coluna dopost
ID da tabelaPrimary Key
:E, a
tag_id
coluna napost_tag
tabela possui umForeign Key
relacionamento com a coluna detag
identificação da tabelaPrimary Key
:Usando o
@ManyToMany
mapeamento JPAÉ assim que você pode mapear o
many-to-many
relacionamento da tabela com JPA e Hibernate:tags
associação naPost
entidade define apenas os tiposPERSIST
eMERGE
cascata. Conforme explicado neste artigo , aREMOVE
transição de estado da entidade não faz sentido para uma@ManyToMany
associação JPA, pois pode desencadear uma exclusão de cadeia que acabaria com os dois lados da associação.Post
entidade usa o identificador de entidade para igualdade, uma vez que não possui nenhuma chave comercial exclusiva. Conforme explicado neste artigo , você pode usar o identificador de entidade para igualdade, desde que ele se mantenha consistente em todas as transições de estado da entidade .Tag
entidade possui uma chave comercial exclusiva, marcada com a@NaturalId
anotação específica do Hibernate . Nesse caso, a chave comercial exclusiva é o melhor candidato para verificações de igualdade .mappedBy
atributo daposts
associação naTag
entidade marca que, nesse relacionamento bidirecional, oPost
entidade possui a associação. Isso é necessário, pois apenas um lado pode possuir um relacionamento e as alterações são propagadas apenas para o banco de dados desse lado específico.Set
deve ser preferido, pois usar umList
com@ManyToMany
é menos eficiente.fonte
isso provavelmente exigiria uma relação de muitos para muitos da seguinte maneira
pode ser necessário definir um joinTable + JoinColumn, mas também será possível trabalhar sem ...
fonte
Eu explicaria assim:
OneToOne - relacionamento OneToOne
OneToMany - relacionamento ManyToOne
ManyToMany - relacionamento ManyToMany
fonte
Antes de tudo, leia todas as letras pequenas. Observe que o mapeamento relacional do NHibernate (portanto, eu também assumo o Hibernate) tem uma correspondência engraçada com o mapeamento de banco de dados e gráfico de objetos. Por exemplo, os relacionamentos um para um são frequentemente implementados como um relacionamento muitos para um.
Segundo, antes que possamos dizer como você deve escrever seu mapa de O / R, também precisamos ver seu banco de dados. Em particular, uma única Habilidade pode ser possuída por várias pessoas? Nesse caso, você tem um relacionamento muitos-para-muitos; caso contrário, é muitos-para-um.
Terceiro, prefiro não implementar relacionamentos muitos-para-muitos diretamente, mas sim modelar a "tabela de junção" em seu modelo de domínio - ou seja, tratá-la como uma entidade, assim:
Então você vê o que tem? Você tem dois relacionamentos um para muitos. (Nesse caso, a pessoa pode ter uma coleção de habilidades pessoais, mas não teria uma coleção de habilidades.) No entanto, alguns preferem usar o relacionamento muitos-para-muitos (entre pessoa e habilidade); isso é controverso.
Quarto, se você tiver relacionamentos bidirecionais (por exemplo, não apenas a Pessoa possui uma coleção de Habilidades, mas também a Skill possui uma coleção de Pessoas), o NHibernate não impõe a bidirecionalidade no seu BL para você; entende apenas a bidirecionalidade dos relacionamentos para fins de persistência.
Em quinto lugar, é muito mais fácil usar corretamente um no outro para um no NHibernate (e eu assumo o Hibernate) do que um para muitos (mapeamento de coleção).
Boa sorte!
fonte