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

主要针对 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

表结构如下:

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 表示如下:

@Entity
public class LoginLog {
    // ...

    @ManyToOne
    private Student student;

    // ...
}

使用 Join Columns

@Entity
public class LoginLog {
    @Id private long id

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

    // ...
}

一对一 (One-to-one)

Student 1--->0..1 StudentProfiles

表结构如下:

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 表示如下:

@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

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

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

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

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

@Entity
public class Student {
    @Id private int id

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

多对多 (Many-to-Many)

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

表结构如下:

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

create table courses (
    id int primary key,
    name varchar(50)
);
@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;

    // ...
}
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

@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.