JPA外键关系映射(终极理解)
OneToOne
OneToOne是一对一关系,由一方的外键保存另一方的主键来维系双方的关系,而另一方需要获取关系映射而不需要维护外键即可获取对方,比如说Person和Address,由Person持有一个字段addr_id,保存Address的id,来维系双方的一对一关系
Person实体类如下:
@Entity
@Table(name = "person")
public class Person {
@Id
@Column(name = "id")
private String id;
@Column
private String name;
/**
* 由person表持有addr_id,保存address表的id
* referencedColumnName是指addr_id指定的address的映射字段,默认是id主键
*/
@OneToOne
@JoinColumn(name = "addr_id", referencedColumnName = "id")
private Address address;
}
双向OneToOne
如果关系由一方维系,而另一方又想获取维系方的数据,比如说Person和Address,关系由Person的addr_id表字段来维系,而在Address实体类中又想获取Person,此时就只需要一个关系映射即可,而不需要Address再搞个外键来维系Person关系
Address实体类如下:
@Entity
@Table(name = "address")
public class Address {
@Id
@Column(name = "id")
private String id;
@Column
private String addrName;
/**
* 一对一的被维系方,指定由Person实体类中的address属性进行关系映射管理
* 从而获取Person数据
*/
@OneToOne(mappedBy = "address")
private Person person;
}
单向OneToMany
OneToMany是一对多的关系,而一般来说外键是存储在多的一方,所以使用单向的OneToMany显得有点怪异,因为此时指定的外键是对方的表字段,比如说Department和Person是一对多,一个部门有多个人员,而两者之间的关系是由Person中的dept_id表字段保存Department中的id主键来维系的,此时在部门类中使用单向OneToMany映射一对多关系时,放的实际是Person表中的dept_id字段
Department实体类如下:
@Entity
@Table(name = "department")
public class Department {
@Id
@Column(name = "id")
private String id;
@Column
private String deptName;
/**
* 单向一对多时,使用JoinColumn进行连接字段映射
* 此时name为对方也就是Person表中的外键dept_id字段,
* 而映射的referencedColumnName是本表的主键id字段
*/
@OneToMany
@JoinColumn(name = "dept_id", referencedColumnName = "id")
private List<Person> peopleList;
}
OneToMany和ManyToOne双向
单向的OneToMany是有点怪异的,因为外键不是存在One一方的表中,所以在一对多时,建议使用OneToMany和ManyToOne配合使用,由Many方使用外键维系关系,而One方只需要指定Many方关系映射的属性即可。
多方使用ManyToOne维系关系,如:Person实体类
@Entity
@Table(name = "person")
public class Person {
@Id
@Column(name = "id")
private String id;
@Column
private String name;
/**
* 多对一关系,由多方维系关系
* 通过person表的dept_id字段和department表的id主键字段做关系映射
*/
@ManyToOne
@JoinColumn(name = "dept_id")
private Department department;
}
少方使用OneToMany,获取映射,如:Department实体类
@Entity
@Table(name = "department")
public class Department {
@Id
@Column(name = "id")
private String id;
@Column
private String deptName;
/**
* OneToMany和ManyToOne配合使用时,由ManyToOne多方进行关系管理
* 此时只需要指定管理映射属性,为Person中的department属性
*/
@OneToMany(mappedBy = "department")
private List<Person> peopleList;
}
ManyToMany
多对多的关系中,往往需要借助第三张表,而这第三张表可以由JPA自动生成,此时就需要借助@JoinTable来自动生成第三张表,进行外键的管理,而@JoinTable由那一方指定都是可以的,另一方无需指定
Person实体类如下:
@Entity
@Table(name = "person")
public class Person {
@Id
@Column(name = "id")
private String id;
@Column
private String name;
/**
* 多对多,通过JoinTable生成第三方表,指定各自主键的存放列名
* joinColumns:将本表id,存储到第三方表,列名为per_id
* inverseJoinColumns:将对方表id,存储到第三方表,列名为dept_id
* 注意:此处存放到第三方表的列名,需要和对方的外键名称相一致
*/
@ManyToMany
@JoinTable(
name = "pro_dept", // 自动生成的第三方表名,可省略
joinColumns = @JoinColumn(name = "per_id"), // 将本表id,存储到第三方表,列名为per_id
inverseJoinColumns = @JoinColumn(name = "dept_id") // 将对方表id,存储到第三方表,列名为dept_id
)
private List<Department> department;
}
Department实体类如下:
@Entity
@Table(name = "department")
public class Department {
@Id
@Column(name = "id")
private String id;
@Column
private String deptName;
/**
* 通过mappedBy表明由Person实体的department属性进行关系管理
*/
@ManyToMany(mappedBy = "department")
private List<Person> personList;
}
上一篇: 学习jpa的级联
下一篇: 心得体会PartIV