Na seção de exemplo da @OneToMany
referência de anotação JPA :
Exemplo 1-59 @OneToMany - Classe de cliente com genéricos
@Entity
public class Customer implements Serializable {
...
@OneToMany(cascade=ALL, mappedBy="customer")
public Set<Order> getOrders() {
return orders;
}
...
}
Exemplo 1-60 @ManyToOne - Classe de ordem com genéricos
@Entity
public class Order implements Serializable {
...
@ManyToOne
@JoinColumn(name="CUST_ID", nullable=false)
public Customer getCustomer() {
return customer;
}
...
}
Parece-me que a Customer
entidade é a proprietária da associação. No entanto, na explicação para o mappedBy
atributo no mesmo documento, está escrito que:
se o relacionamento for bidirecional, defina o elemento mappedBy no lado inverso (não proprietário) da associação como o nome do campo ou propriedade que possui o relacionamento, como mostra o Exemplo 1-60.
No entanto, se não estou errado, parece que no exemplo, o mappedBy
é realmente especificado no lado proprietário da associação, em vez do lado não proprietário.
Então, minha pergunta é basicamente:
Em uma associação bidirecional (um para muitos / muitos para um), qual das entidades é o proprietário? Como podemos designar o lado Único como proprietário? Como podemos designar o lado Muitos como o proprietário?
O que se entende por "o lado inverso da associação"? Como podemos designar o lado Um como o inverso? Como podemos designar o lado Muitos como o inverso?
Respostas:
Para entender isso, você deve dar um passo atrás. No OO, o cliente possui os pedidos (os pedidos são uma lista no objeto do cliente). Não pode haver um pedido sem um cliente. Portanto, o cliente parece ser o proprietário dos pedidos.
Mas no mundo do SQL, um item realmente conterá um ponteiro para o outro. Como há 1 cliente para N pedidos, cada pedido contém uma chave estrangeira para o cliente ao qual ele pertence. Essa é a "conexão" e significa que a ordem "possui" (ou contém literalmente) a conexão (informações). Isso é exatamente o oposto do mundo OO / modelo.
Isso pode ajudar a entender:
O lado inverso é o OO "proprietário" do objeto, neste caso o cliente. O cliente não possui colunas na tabela para armazenar os pedidos, portanto, é necessário informar onde ele pode salvar esses dados na tabela de pedidos (o que acontece via
mappedBy
).Outro exemplo comum são as árvores com nós, que podem ser pais e filhos. Nesse caso, os dois campos são usados em uma classe:
Isso explica as obras de design muitos-para-um da "chave estrangeira". Existe uma segunda abordagem que usa outra tabela para manter as relações. Isso significa que, para o nosso primeiro exemplo, você tem três tabelas: aquela com clientes, aquela com pedidos e uma tabela de duas colunas com pares de chaves primárias (customerPK, orderPK).
Essa abordagem é mais flexível que a acima (ela pode lidar facilmente com um para um, muitos para um, um para muitos e até muitos para muitos). O preço é esse
É por isso que eu raramente recomendo essa abordagem.
fonte
@Parent
ou@Child
anotação em vez de "XtoY" para o estado que os de conexão meios (em vez de como ele é implementado )Inacreditavelmente, em três anos, ninguém respondeu à sua excelente pergunta com exemplos das duas maneiras de mapear o relacionamento.
Conforme mencionado por outros, o lado "proprietário" contém o ponteiro (chave estrangeira) no banco de dados. Você pode designar ambos os lados como proprietário, no entanto, se você designar o lado Único como proprietário, o relacionamento não será bidirecional (o lado inverso, conhecido como "muitos", não terá conhecimento de seu "proprietário"). Isso pode ser desejável para encapsulamento / acoplamento solto:
A única solução de mapeamento bidirecional é ter o lado "many" como ponteiro para o "one" e usar o atributo @OneToMany "mappedBy". Sem o atributo "mappedBy", o Hibernate esperará um mapeamento duplo (o banco de dados terá a coluna de junção e a tabela de junção, que é redundante (geralmente indesejável)).
fonte
A entidade que possui a tabela com chave estrangeira no banco de dados é a entidade proprietária e a outra tabela, sendo apontada, é a entidade inversa.
fonte
Regras simples de relacionamentos bidirecionais:
1.Para relacionamentos bidirecionais muitos-para-um, o lado muitos é sempre o lado proprietário do relacionamento. Exemplo: 1 quarto tem muitas pessoas (uma pessoa pertence apenas a um quarto) -> o lado proprietário é a pessoa
2.Para relacionamentos bidirecionais um para um, o lado proprietário corresponde ao lado que contém a chave estrangeira correspondente.
3.Para relacionamentos bidirecionais muitos para muitos, ambos os lados podem ser o proprietário.
A esperança pode ajudá-lo.
fonte
Para duas Classes de Entidade Cliente e Pedido, o hibernate criará duas tabelas.
Casos possíveis:
mappedBy não é usado nas classes Customer.java e Order.java;
No lado do cliente, será criada uma nova tabela [name = CUSTOMER_ORDER], que manterá o mapeamento de CUSTOMER_ID e ORDER_ID. Essas são chaves primárias das tabelas de clientes e pedidos. No lado do pedido, é necessária uma coluna adicional para salvar o mapeamento de registro Customer_ID correspondente.
mappedBy é usado em Customer.java [Conforme fornecido na declaração do problema] Agora, a tabela adicional [CUSTOMER_ORDER] não é criada. Apenas uma coluna na tabela de pedidos
mappedby é usado em Order.java Agora, uma tabela adicional será criada pelo hibernate. [name = CUSTOMER_ORDER] A tabela de pedidos não terá a coluna adicional [Customer_ID] para o mapeamento.
Qualquer lado pode ser nomeado proprietário do relacionamento. Mas é melhor escolher o lado xxxToOne.
Efeito de codificação -> Somente o lado proprietário da entidade pode alterar o status do relacionamento. No exemplo abaixo, a classe BoyFriend é proprietária do relacionamento. mesmo se namorada quiser terminar, ela não pode.
fonte
Relacionamentos de tabela vs. relacionamentos de entidade
Em um sistema de banco de dados relacional, pode haver apenas três tipos de relacionamentos de tabela:
Portanto, um
one-to-many
relacionamento de tabela é o seguinte:Observe que o relacionamento é baseado na coluna Chave estrangeira (por exemplo,
post_id
) na tabela filha.Portanto, existe uma única fonte de verdade quando se trata de gerenciar um
one-to-many
relacionamento de tabela.Agora, se você usar um relacionamento de entidade bidirecional que mapeie o
one-to-many
relacionamento de tabela que vimos anteriormente:Se você der uma olhada no diagrama acima, poderá ver que existem duas maneiras de gerenciar esse relacionamento.
Na
Post
entidade, você tem acomments
coleção:E, no
PostComment
, apost
associação é mapeada da seguinte maneira:Portanto, você tem dois lados que podem alterar a associação da entidade:
comments
coleção filha, uma novapost_comment
linha deve ser associada àpost
entidade pai por meio de suapost_id
coluna.post
propriedade daPostComment
entidade, apost_id
coluna também deve ser atualizada.Como existem duas maneiras de representar a coluna Chave Externa, você deve definir qual é a fonte da verdade quando se trata de converter a alteração do estado da associação em sua modificação equivalente no valor da coluna Chave Externa.
MappedBy (também conhecido como lado inverso)
O
mappedBy
atributo informa que o@ManyToOne
lado é responsável pelo gerenciamento da coluna Chave Externa, e a coleção é usada apenas para buscar as entidades filhas e fazer cascata de alterações no estado da entidade pai para filhos (por exemplo, remover o pai também deve remover as entidades filho).Sincronize os dois lados de uma associação bidirecional
Agora, mesmo se você definiu o
mappedBy
atributo e a@ManyToOne
associação do lado filho gerencia a coluna Chave Externa, ainda é necessário sincronizar os dois lados da associação bidirecional.A melhor maneira de fazer isso é adicionar esses dois métodos utilitários:
Os métodos
addComment
eremoveComment
garantem que ambos os lados estejam sincronizados. Portanto, se adicionarmos uma entidade filha, a entidade filha precisará apontar para o pai e a entidade pai deverá ter o filho contido na coleção filho.fonte