Esta é uma pergunta muito comum, portanto, esta resposta é baseada neste artigo que escrevi no meu blog.
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 Keycoluna no filho que faz referência à Primary Keylinha da tabela pai.
No diagrama da tabela acima, a post_idcoluna da post_commenttabela possui um Foreign Keyrelacionamento com a coluna do postID da tabela Primary Key:
ALTER TABLE
post_comment
ADD CONSTRAINT
fk_post_comment_post_id
FOREIGN KEY (post_id) REFERENCES post
Anotação @ManyToOne
A melhor maneira de mapear o relacionamento de uma para muitas tabelas é usar a @ManyToOneanotação.
No nosso caso, a entidade filha PostCommentmapeia a post_idcoluna Chave estrangeira usando a @ManyToOneanotação:
@Entity(name = "PostComment")
@Table(name = "post_comment")
public class PostComment {
@Id
@GeneratedValue
private Long id;
private String review;
@ManyToOne(fetch = FetchType.LAZY)
private Post post;
}
Usando a @OneToManyanotação JPA
Só porque você tem a opção de usar a @OneToManyanotaçã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 @OneToManyassociação é confiar no @ManyToOnelado para propagar todas as alterações de estado da entidade:
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
//Constructors, getters and setters removed for brevity
public void addComment(PostComment comment) {
comments.add(comment);
comment.setPost(this);
}
public void removeComment(PostComment comment) {
comments.remove(comment);
comment.setPost(null);
}
}
A entidade pai Post, apresenta dois métodos utilitários (por exemplo, addCommente removeComment) 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 @OneToManyassociação unidirecional deve ser evitada, pois é menos eficiente do que o uso @ManyToOneou a @OneToManyassociação bidirecional .
Para obter mais detalhes sobre a melhor maneira de mapear o @OneToManyrelacionamento com JPA e Hibernate, consulte este artigo .
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 Keycoluna no filho, que também é uma Foreign Keyreferência à Primary Keylinha da tabela pai.
Portanto, podemos dizer que a tabela filho compartilha Primary Keycom a tabela pai.
No diagrama da tabela acima, a idcoluna na post_detailstabela também possui um Foreign Keyrelacionamento com a coluna da posttabela id Primary Key:
ALTER TABLE
post_details
ADD CONSTRAINT
fk_post_details_id
FOREIGN KEY (id) REFERENCES post
Usando o JPA @OneToOnecom@MapsId anotações
A melhor maneira de mapear um @OneToOnerelacionamento é usar @MapsId. Dessa forma, você nem precisa de uma associação bidirecional, pois sempre pode buscar a PostDetailsentidade usando o métodoPost identificador entidade.
O mapeamento fica assim:
[code language = "java"] @Entity (name = "PostDetails") @Table (name = "post_details") classe pública PostDetails {
@Id
private Long id;
@Column(name = "created_on")
private Date createdOn;
@Column(name = "created_by")
private String createdBy;
@OneToOne(fetch = FetchType.LAZY)
@MapsId
@JoinColumn(name = "id")
private Post post;
public PostDetails() {}
public PostDetails(String createdBy) {
createdOn = new Date();
this.createdBy = createdBy;
}
//Getters and setters omitted for brevity
} [/ código]
Dessa forma, a idpropriedade serve como Chave Primária e Chave Externa. Você notará que a @Idcoluna não usa mais uma @GeneratedValueanotação, pois o identificador é preenchido com o identificador da postassociação.
Para obter mais detalhes sobre a melhor maneira de mapear o @OneToOnerelacionamento com JPA e Hibernate, consulte este artigo .
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 Keycolunas referenciando as Primary Keycolunas das duas tabelas pai.
No diagrama da tabela acima, a post_idcoluna da post_tagtabela também possui um Foreign Keyrelacionamento com a coluna do postID da tabela Primary Key:
ALTER TABLE
post_tag
ADD CONSTRAINT
fk_post_tag_post_id
FOREIGN KEY (post_id) REFERENCES post
E, a tag_idcoluna na post_tagtabela possui um Foreign Keyrelacionamento com a coluna de tagidentificação da tabela Primary Key:
ALTER TABLE
post_tag
ADD CONSTRAINT
fk_post_tag_tag_id
FOREIGN KEY (tag_id) REFERENCES tag
Usando o @ManyToManymapeamento JPA
É assim que você pode mapear o many-to-manyrelacionamento da tabela com JPA e Hibernate:
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
@JoinTable(name = "post_tag",
joinColumns = @JoinColumn(name = "post_id"),
inverseJoinColumns = @JoinColumn(name = "tag_id")
)
private Set<Tag> tags = new HashSet<>();
//Getters and setters ommitted for brevity
public void addTag(Tag tag) {
tags.add(tag);
tag.getPosts().add(this);
}
public void removeTag(Tag tag) {
tags.remove(tag);
tag.getPosts().remove(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Post)) return false;
return id != null && id.equals(((Post) o).getId());
}
@Override
public int hashCode() {
return 31;
}
}
@Entity(name = "Tag")
@Table(name = "tag")
public class Tag {
@Id
@GeneratedValue
private Long id;
@NaturalId
private String name;
@ManyToMany(mappedBy = "tags")
private Set<Post> posts = new HashSet<>();
//Getters and setters ommitted for brevity
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Tag tag = (Tag) o;
return Objects.equals(name, tag.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
- A
tagsassociação na Postentidade define apenas os tipos PERSISTe MERGEcascata. Conforme explicado neste artigo , a REMOVE transição de estado da entidade não faz sentido para uma @ManyToManyassociação JPA, pois pode desencadear uma exclusão de cadeia que acabaria com os dois lados da associação.
- Conforme explicado neste artigo , os métodos do utilitário adicionar / remover são obrigatórios se você usar associações bidirecionais para garantir que os dois lados da associação estejam sincronizados.
- A
Postentidade 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 .
- A
Tagentidade possui uma chave comercial exclusiva, marcada com a @NaturalIdanotação específica do Hibernate . Nesse caso, a chave comercial exclusiva é o melhor candidato para verificações de igualdade .
- O
mappedByatributo da postsassociação na Tagentidade 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.
- O
Setdeve ser preferido, pois usar um Listcom @ManyToManyé menos eficiente.
Para obter mais detalhes sobre a melhor maneira de mapear o @ManyToManyrelacionamento com JPA e Hibernate, consulte este artigo .