以下将讲解关系型数据的关系描述。仅仅是作为总结。

主要针对 JPA 进行详解

关于关系型数据库的关系

关系的概念(Relationship)

角色 (Roles)

现实中的人称关系,有你、我、她、他、它、你们、我们、她们、她们和它们,而在数据库中的两个实体的关系通俗的将有这边儿、对面以及两边。

Student — Course

方向性 (Directoionality)

实体中关系的方向性主要有两种,一种是双向关系,另一种则是单向关系。

双向 (bidirectional)

Student <---> Course

单向 (unidirectional)

Student —> LoginLog

当然双向关系的可以拆分为两个单向关系。

源(Source) 目标 (Target)
Student —> Course
目标(Target) 源 (Source)
Student <— Course

基数 (Cardinality)

在关系中的每一个角色都会有独自的基数。

LoginLog *—>1 Student
单向“多对一” (many-to-one)关系

这里学生的基数是 1(一个登录日志仅仅只属于某一个学生,所以学生属于 one 一边),而登录日志的基数用”*“标识(一个学生可以有多个登录日志,登录日志属于 many 一边)。

Student *<--->* Course
双向“多对多” (many-to-many)关系

序数 (Ordinality)

当源(Source)实体完成创建后,目标(Target)实体是否需要被指定就靠序数来决定,一般用 0 或者 1 标识。

映射 (Mappings)

数据映射主要有一下四种:

  • 多对一 (Many-to-one)
  • 一对一 (One-to-one)
  • 一对多 (One-to-Many)
  • 多对多 (Many-to-Many)

从整体上也分为:

  • 单值关联 (Single-Valued Associations)
  • 集合值关联 (Collection-Valued Associations)

单值关联 (Single-Valued Associations)

如果关系中目标实体的基数为 1,这种就成为单值联系。如“多对一”和“一对一”。

多对一 (Many-to-one)

LoingLog *—>1 Student

表结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
create table login_logs (
id long primary key,
log_ip int,
log_at timestamp,
stu_id int,
foreign key(stu_id) references students(id)
);

create table students (
id int primary key,
name varchar(20)
);

用 JPA 表示如下:

1
2
3
4
5
6
7
8
9
@Entity
public class LoginLog {
// ...

@ManyToOne
private Student student;

// ...
}

使用 Join Columns

1
2
3
4
5
6
7
8
9
10
@Entity
public class LoginLog {
@Id private long id

@ManyToOne
@JoinColumn(name = "stu_id")
private Student student;

// ...
}

一对一 (One-to-one)

Student 1—>0..1 StudentProfiles

表结构如下:

1
2
3
4
5
6
7
8
9
10
11
create table students (
id int primary key,
name varchar(20)
);

create table student_profiles (
id int primary key,
gender tinyint,
stu_id int,
foreign key(stu_id) references students(id)
);

用 JPA 表示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Entity
public class StudentProfile {
@Id private int id;

@OneToOne
@JoinColumn(name = "stu_id")
private Student student;
}

@Entity
public class Student {
@Id private int id;

@OneToOne(mappedBy = "student")
private StudentProfile profile;

// ...
}

集合值关联 (Collection-Valued Associations)

一对多和多对多关系中都有一个共同点就是都有多个 (many) 目标实体,这样的关联就称之为集合值关联。

一对多 (One-to-Many)

Student 1—>* LoginLog

表结构在这里就不再赘述。

1
2
3
4
5
6
7
@Entity
public class Student {
@Id private int id;

@OneToMany(mappedBy = "student")
private Collection<LoginLog> logs;
}

也可以使用 targetEntity 来指定集合中元素类型。

1
2
3
4
5
6
7
@Entity
public class Student {
@Id private int id

@OneToMany(targetEntity = LoginLog.class, mappedBy = "student")
private Collection logs;
}

多对多 (Many-to-Many)

Student *<--->* Course
双向关系

表结构如下:

1
2
3
4
5
6
7
8
9
create table students (
id int primary key,
name varchar(20)
);

create table courses (
id int primary key,
name varchar(50)
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Entity
public class Student {
@Id private int id;

@ManyToMany
private Collection<Course> courses;

// ...
}

@Entity
public class Course {
@Id private int id;

@ManyToMany(mappedBy = "courses")
private Collection<Student> students;

// ...
}
1
2
3
4
5
6
7
create table records (
stu_id int,
crs_id int,
primary key (stu_id, crs_id),
foreign key (stu_id) references students(id),
foreign key (crs_id) references courses(id)
);

使用 Join Tables

1
2
3
4
5
6
7
8
9
10
@Entity
public class Student {
@Id private int id;

@ManyToMany
@JoinTable(name = "records",
joinColumns = @JoinColumn(name = "stu_id"),
inverseJoinColumns = @JoinColumn(name = "crs_id"))
private Collection<Course> courses;
}

关系还需亲自理清,所以建议读者自己动手理一下,效果会更好。

References

Pro JPA 2 in Java EE 8, 3rd Edition. Mike Keith, Merrick Schincariol, Massimo Nardone. 2018.