Qual é a diferença entre:
@Entity
public class Company {
@OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY)
@JoinColumn(name = "companyIdRef", referencedColumnName = "companyId")
private List<Branch> branches;
...
}
e
@Entity
public class Company {
@OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY, mappedBy = "companyIdRef")
private List<Branch> branches;
...
}
Respostas:
A anotação
@JoinColumn
indica que esta entidade é o proprietário do relacionamento (ou seja: a tabela correspondente possui uma coluna com uma chave estrangeira para a tabela referenciada), enquanto o atributomappedBy
indica que a entidade deste lado é o inverso do relacionamento, e o proprietário reside na "outra" entidade. Isso também significa que você pode acessar a outra tabela da classe que você anotou com "mappedBy" (relacionamento totalmente bidirecional).Em particular, para o código da pergunta, as anotações corretas teriam a seguinte aparência:
fonte
@JoinColumn
emCompany
Branch
não tiver uma propriedade que faça referênciaCompany
, mas a tabela subjacente tiver uma coluna que tenha, você poderá usar@JoinTable
para mapeá-la. Essa é uma situação incomum, porque você normalmente mapeia a coluna no objeto que corresponde à sua tabela, mas pode acontecer e é perfeitamente legítima.@OneToOne
, as linhas filho são atualizadas com umnull
na coluna FKey que faz referência ao pai.@JoinColumn
poderia ser usado nos dois lados do relacionamento. A pergunta era sobre o uso@JoinColumn
ao@OneToMany
lado (caso raro). E o ponto aqui é a duplicação de informações físicas (nome da coluna) junto com a consulta SQL não otimizada que produzirá algumasUPDATE
instruções adicionais .De acordo com a documentação :
Como muitos para um são (quase) sempre o lado proprietário de um relacionamento bidirecional na especificação da JPA, a associação de um para muitos é anotada por
@OneToMany(mappedBy=...)
Troop
tem um relacionamento bidirecional com muitosSoldier
através da propriedade da tropa. Você não precisa (não deve) definir nenhum mapeamento físico nomappedBy
lado.Para mapear um bidirecional para muitos, com o lado um para muitos como o lado proprietário , você deve remover o
mappedBy
elemento e definir os muitos para um@JoinColumn
comoinsertable
eupdatable
false. Esta solução não é otimizada e produzirá algumasUPDATE
instruções adicionais .fonte
mappedBy="troop"
refere a qual campo?mappedBy="troop"
se refere à tropa de propriedades na classe Soldier. No código acima, a propriedade não é visível porque aqui Mykhaylo a omitiu, mas você pode deduzir sua existência pelo getter getTroop (). Verifique a resposta de Óscar López , é muito claro e você entenderá.Associação unidirecional um para muitos
Como expliquei neste artigo , se você usar a
@OneToMany
anotação com@JoinColumn
, terá uma associação unidirecional, como a que existe entre aPost
entidade pai e o filhoPostComment
no diagrama a seguir:Ao usar uma associação unidirecional um para muitos, apenas o lado dos pais mapeia a associação.
Neste exemplo, apenas a
Post
entidade definirá uma@OneToMany
associação àPostComment
entidade filha :Associação bidirecional um para muitos
Se você usar o
@OneToMany
com omappedBy
conjunto de atributos, você terá uma associação bidirecional. No nosso caso, aPost
entidade possui uma coleção dePostComment
entidades filhas e aPostComment
entidade filha possui uma referência àPost
entidade pai , conforme ilustrado no diagrama a seguir:Na
PostComment
entidade, apost
propriedade da entidade é mapeada da seguinte maneira:Na
Post
entidade, acomments
associação é mapeada da seguinte maneira:O
mappedBy
atributo da@OneToMany
anotação faz referência àpost
propriedade naPostComment
entidade filha e, dessa forma, o Hibernate sabe que a associação bidirecional é controlada pelo@ManyToOne
lado, responsável por gerenciar o valor da coluna Chave Externa na qual o relacionamento da tabela se baseia.Para uma associação bidirecional, você também precisa ter dois métodos utilitários, como
addChild
eremoveChild
:Esses dois métodos garantem que os dois lados da associação bidirecional não sejam sincronizados. Sem sincronizar as duas extremidades, o Hibernate não garante que as mudanças no estado da associação sejam propagadas para o banco de dados.
Qual escolher?
A associação unidirecional
@OneToMany
não funciona muito bem ; portanto, você deve evitá-la.É melhor usar o bidirecional
@OneToMany
que é mais eficiente .fonte
A anotação mappedBy idealmente sempre deve ser usada no lado pai (classe Company) do relacionamento bidirecional, nesse caso, deve estar na classe Company apontando para a variável de membro 'company' da classe Child (classe Branch)
A anotação @JoinColumn é usada para especificar uma coluna mapeada para ingressar em uma associação de entidade. Essa anotação pode ser usada em qualquer classe (pai ou filho), mas idealmente deve ser usada apenas em um lado (na classe pai ou na classe filho não em ambos) aqui, neste caso, usei-o no lado filho (classe Branch) da relação bidirecional, indicando a chave estrangeira na classe Branch.
abaixo está o exemplo de trabalho:
classe pai, empresa
classe infantil, Filial
fonte
Gostaria apenas de acrescentar que
@JoinColumn
nem sempre é necessário estar relacionado ao local da informação física, como sugere esta resposta. Você pode combinar@JoinColumn
com@OneToMany
mesmo que a tabela pai não possua dados da tabela apontando para a tabela filha.Como definir o relacionamento OneToMany unidirecional no JPA
OneToMany unidirecional, sem ManyToOne inverso, sem tabela de associação
Parece estar disponível apenas no
JPA 2.x+
entanto. É útil para situações em que você deseja que a classe filho contenha apenas o ID do pai, não uma referência completa.fonte
Discordo da resposta aceita aqui por Óscar López. Essa resposta é imprecisa!
NÃO é o
@JoinColumn
que indica que esta entidade é o proprietário do relacionamento. Em vez disso, é o@ManyToOne
anotação que faz isso (no exemplo dele).As anotações de relacionamento, como
@ManyToOne
,@OneToMany
e@ManyToMany
dizem ao JPA / Hibernate para criar um mapeamento. Por padrão, isso é feito através de uma Tabela de associação separada.@JoinColumn
MappedBy
Lembre-se:
MappedBy
é uma propriedade das anotações de relacionamento cujo objetivo é gerar um mecanismo para relacionar duas entidades que, por padrão, o fazem criando uma tabela de junção.MappedBy
interrompe esse processo em uma direção.MappedBy
Diz-se que a entidade que não está usando é a proprietária do relacionamento porque a mecânica do mapeamento é ditada dentro de sua classe através do uso de uma das três anotações de mapeamento no campo de chave estrangeira. Isso não apenas especifica a natureza do mapeamento, mas também instrui a criação de uma tabela de junção. Além disso, a opção de suprimir a tabela de junção também existe aplicando a anotação @JoinColumn sobre a chave estrangeira, que a mantém dentro da tabela da entidade proprietária.Em resumo:
@JoinColumn
cria uma nova coluna de junção ou renomeia uma existente; enquanto oMappedBy
parâmetro trabalha em colaboração com as anotações de relacionamento da outra classe (filha) para criar um mapeamento por meio de uma tabela de junção ou criando uma coluna de chave estrangeira na tabela associada da entidade proprietária.Para ilustrar como
MapppedBy
funciona, considere o código abaixo. Se oMappedBy
parâmetro fosse excluído, o Hibernate criaria DUAS tabelas de junção! Por quê? Como existe simetria nos relacionamentos muitos para muitos, o Hibernate não tem lógica para selecionar uma direção em relação à outra.Portanto, usamos
MappedBy
para informar ao Hibernate que escolhemos a outra entidade para ditar o mapeamento do relacionamento entre as duas entidades.Adicionar @JoinColumn (name = "driverID") na classe do proprietário (veja abaixo) impedirá a criação de uma tabela de junção e, em vez disso, criará uma coluna de chave estrangeira driverID na tabela Cars para construir um mapeamento:
fonte
JPA é uma API em camadas, os diferentes níveis têm suas próprias anotações. O nível mais alto é o (1) nível de entidade que descreve as classes persistentes; então, você tem o (2) nível de banco de dados relacional que assume que as entidades estão mapeadas para um banco de dados relacional e (3) o modelo java.
Nível 1 anotações:
@Entity
,@Id
,@OneToOne
,@OneToMany
,@ManyToOne
,@ManyToMany
. Você pode introduzir persistência no seu aplicativo usando apenas essas anotações de alto nível. Mas então você deve criar seu banco de dados de acordo com as suposições que o JPA faz. Essas anotações especificam o modelo de entidade / relacionamento.Nível 2 anotações:
@Table
,@Column
,@JoinColumn
, ... Influência do mapeamento de entidades / propriedades para as tabelas de banco de dados relacionais / colunas se você não estiver satisfeito com os padrões da APP ou se você precisa mapear para um banco de dados existente. Essas anotações podem ser vistas como anotações de implementação, especificando como o mapeamento deve ser feito.Na minha opinião, é melhor manter o máximo possível as anotações de alto nível e, em seguida, introduzir as anotações de nível inferior, conforme necessário.
Para responder às perguntas: o
@OneToMany
/mappedBy
é melhor porque usa apenas as anotações do domínio da entidade. O@oneToMany
/@JoinColumn
também é bom, mas usa uma anotação de implementação onde isso não é estritamente necessário.fonte
Deixe-me simplificar.
Você pode usar @JoinColumn em ambos os lados, independentemente do mapeamento.
Vamos dividir isso em três casos.
1) Mapeamento unidirecional da Filial para a Empresa.
2) Mapeamento bidirecional da empresa para a filial.
3) Somente mapeamento unidirecional da empresa para a filial.
Portanto, qualquer caso de uso se enquadra nessas três categorias. Então, deixe-me explicar como usar @JoinColumn e mappedBy .
1) Mapeamento unidirecional da Filial para a Empresa.
Use JoinColumn na tabela Filial.
2) Mapeamento bidirecional da empresa para a filial.
Use a tabela mappedBy in Company, conforme descrito pela resposta de @Mykhaylo Adamovych.
3) Mapeamento unidirecional da empresa para a filial.
Basta usar @JoinColumn na tabela Empresa.
Isso diz que, com base no mapeamento da chave estrangeira "courseId" na tabela branches, me dê uma lista de todos os branches. NOTA: neste caso, não é possível buscar a empresa da filial, apenas o mapeamento unidirecional existe de empresa para filial.
fonte