一对一
单向一对一
首先来定义我们的实体,People。一个人只能有一个身份证,所以在IdentityCard上我们添加@OneToOne注解用于修饰该关系。
@Entity(name = "people")
public class People {
@Id
@GeneratedValue
private Long id;
@OneToOne
private IdentityCard identityCard;
}
- 该注解会在people的表中生成字段为identity_card_id的列,这表明这种一对一的关系是由People来维护的。
- 在identityCard上我们还可以添加@JoinColumn(name = “identity_card_id”)注解,如果name不指定,则使用默认值。如果指定则列明为指定值。
双向一对一
除了使用@JoinColumn注解来维护People和IdentityCard之间的关系,我们还可以在定义@OneToOne时添加mappedBy。例如:
@Entity(name = "people")
public class People {
@Id
@GeneratedValue
private Long id;
@OneToOne(mappedBy = "people",)
private IdentityCard identityCard;
}
- mappedBy(对应XML配置中的inverse)表明这种关系是由IdentityCard来维护的,而且在IdentityCard中必须有命名为people的字段,该字段被@OneToOne注解修饰
- 在identityCard表中会生成名为people_id的字段,但是在people表中不会有外键生成。
joinColumn和mappedBy的区别
- 使用joinColumn表明这种关系自身来维护,mappedBy表明关系由另一方来维护。
- 如果使用joinCoumn在一对多的时候,在保存一的那方时,会多生成几条对于多的update命令。因为在保存的时候,一的那方不知道多的那方的外键是否正确的保存。
- 如果使用mappedBy,在保存的时候,最终只会有一条update命令用于对一的那方的更新。所以在性能上来看mappedBy是较好的。
一对多
单向一对多
当然,在实际中人和身份证不会存在一对多的关系。
@Entity(name = "people")
public class People {
@Id
@GeneratedValue
private Long id;
@OneToMany
private List<IdentityCard> identityCards;
}
- 如果只是在People中使用@OneToMany注解,则会生成额外一张表来维护这种关系。其中表字段为people_id和identity_card_id。
- 如果不想生成额外的表,则可以使用@JoinColumn(name = “people_id”)。该注解会在identityCard表中新增一列外键people_id,因为一对多的关系是在多的一方那来表现出来的。你总不能在一的一方维护多的所有的id吧。
双向一对多
定义双向一对多关系,则在多的一方添加@ManyToOne注解。还记得为了避免生成额外的表,我们使用@JoinColumn注解来生成外键。但是使用@JoinColumn注解会存在我们上面提到的性能问题。所以在双向关系中我们可以在定义@OneToMany时使用mappedBy,将关系的主控方交给多的一方。