Esta es una pregunta muy común, por lo que esta respuesta se basa en este artículo que escribí en mi blog.
Uno a muchos
La relación de la tabla uno a muchos se ve de la siguiente manera:

En un sistema de base de datos relacional, una relación de tabla de uno a muchos vincula dos tablas basadas en una Foreign Keycolumna en el elemento secundario que hace referencia a la Primary Keyfila de la tabla principal.
En el diagrama de la tabla anterior, la post_idcolumna en la post_commenttabla tiene una Foreign Keyrelación con la columna de postid de la tabla Primary Key:
ALTER TABLE
post_comment
ADD CONSTRAINT
fk_post_comment_post_id
FOREIGN KEY (post_id) REFERENCES post
Anotación @ManyToOne
La mejor manera de mapear la relación de la tabla uno a muchos es usar la @ManyToOneanotación.
En nuestro caso, la entidad secundaria PostCommentasigna la post_idcolumna Clave externa utilizando la @ManyToOneanotación:
@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 la @OneToManyanotación JPA
El hecho de que tenga la opción de usar la @OneToManyanotación, no significa que esta debería ser la opción predeterminada para cada relación de base de datos de uno a muchos . El problema con las colecciones es que solo podemos usarlas cuando el número de registros secundarios es bastante limitado.
La mejor manera de mapear una @OneToManyasociación es confiar en el @ManyToOnelado para propagar todos los cambios de estado de la entidad:
@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);
}
}
La entidad principal Post, presenta dos métodos de utilidad (por ejemplo, addCommenty removeComment) que se utilizan para sincronizar ambos lados de la asociación bidireccional. Siempre debe proporcionar estos métodos siempre que trabaje con una asociación bidireccional ya que, de lo contrario, corre el riesgo de tener problemas de propagación de estado muy sutiles .
La @OneToManyasociación unidireccional debe evitarse ya que es menos eficiente que usar @ManyToOneo la @OneToManyasociación bidireccional .
Para obtener más detalles sobre la mejor manera de mapear la @OneToManyrelación con JPA e Hibernate, consulte este artículo .
Doce y cincuenta y nueve de la noche
La relación de la tabla uno a uno se ve de la siguiente manera:

En un sistema de base de datos relacional, una relación de tabla uno a uno vincula dos tablas basadas en una Primary Keycolumna en el elemento secundario que también hace Foreign Keyreferencia a la Primary Keyfila de la tabla principal.
Por lo tanto, podemos decir que la tabla secundaria comparte Primary Keycon la tabla primaria.
En el diagrama de la tabla anterior, la idcolumna de la post_detailstabla también tiene una Foreign Keyrelación con la columna de la posttabla id Primary Key:
ALTER TABLE
post_details
ADD CONSTRAINT
fk_post_details_id
FOREIGN KEY (id) REFERENCES post
Usando el JPA @OneToOnecon @MapsIdanotaciones
La mejor manera de mapear una @OneToOnerelación es usarla @MapsId. De esta manera, ni siquiera necesita una asociación bidireccional, ya que siempre puede buscar la PostDetailsentidad utilizando el Postidentificador de entidad.
El mapeo se ve así:
[code language = "java"] @Entity (name = "PostDetails") @Table (name = "post_details") clase 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]
De esta manera, la idpropiedad sirve como clave principal y clave externa. Notará que la @Idcolumna ya no usa una @GeneratedValueanotación ya que el identificador se llena con el identificador de la postasociación.
Para obtener más detalles sobre la mejor manera de mapear la @OneToOnerelación con JPA e Hibernate, consulte este artículo .
Muchos a muchos
La relación de tabla de muchos a muchos tiene el siguiente aspecto:

En un sistema de base de datos relacional, una relación de tabla de muchos a muchos vincula dos tablas principales a través de una tabla secundaria que contiene dos Foreign Keycolumnas que hacen referencia a las Primary Keycolumnas de las dos tablas principales.
En el diagrama de la tabla anterior, la post_idcolumna de la post_tagtabla también tiene una Foreign Keyrelación con la columna de postID de la tabla Primary Key:
ALTER TABLE
post_tag
ADD CONSTRAINT
fk_post_tag_post_id
FOREIGN KEY (post_id) REFERENCES post
Y, la tag_idcolumna en la post_tagtabla tiene una Foreign Keyrelación con la columna de tagid de la tabla Primary Key:
ALTER TABLE
post_tag
ADD CONSTRAINT
fk_post_tag_tag_id
FOREIGN KEY (tag_id) REFERENCES tag
Usando el @ManyToManymapeo JPA
Así es como puede mapear la many-to-manyrelación de la tabla con 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);
}
}
- La
tagsasociación en la Postentidad solo define los tipos PERSISTy MERGEcascada. Como se explica en este artículo , la REMOVE transición del estado de la entidad no tiene ningún sentido para una @ManyToManyasociación JPA, ya que podría desencadenar una eliminación de la cadena que finalmente eliminaría ambos lados de la asociación.
- Como se explica en este artículo , los métodos de utilidad de agregar / quitar son obligatorios si usa asociaciones bidireccionales para asegurarse de que ambos lados de la asociación estén sincronizados.
- La
Postentidad utiliza el identificador de entidad para la igualdad, ya que carece de una clave comercial única. Como se explica en este artículo , puede usar el identificador de entidad para la igualdad siempre que se asegure de que sea coherente en todas las transiciones de estado de entidad .
- La
Tagentidad tiene una clave comercial única que está marcada con la @NaturalIdanotación específica de Hibernate . Cuando ese es el caso, la clave comercial única es el mejor candidato para los controles de igualdad .
- El
mappedByatributo de la postsasociación en la Tagentidad marca que, en esta relación bidireccional, la Postentidad posee la asociación. Esto es necesario ya que solo un lado puede ser dueño de una relación, y los cambios solo se propagan a la base de datos desde este lado en particular.
- El
Setes preferible, ya que usar un Listcon @ManyToManyes menos eficiente.
Para obtener más detalles sobre la mejor manera de mapear la @ManyToManyrelación con JPA e Hibernate, consulte este artículo .