3. JPA关系映射

@OneToOne

一对一关联
主要可选属性参数如下:

cascade:级联操作策略;
fetch:数据获取方式;
mappedBy:被关联的属性;
targetEntity:目标类,xxx.class;

cascade:六个属性值可选,通过CascadeType.xxx调用;
fetch:延迟加载和立即加载两种形式,通过FetchType.xxx调用;
mappedBy:可以理解为被映射、被关联、被管理。意为当前类中没有关联关系,关系由另一方管理。而此处填的值就是另一方类中的本方对象名。

下面是一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Entity
public class Teacher {
@Id
private Long t_id;
private String t_name;

@OneToOne(mappedBy = "teacher")
private Student student;

//省略getter setter...
}

@Entity
public class Student {
@Id
private Long s_id;
private String s_name;

@OneToOne(cascade = CascadeType.ALL , fetch = FetchType.LAZY)
@JoinColumn(name = "teacher_id", referencedColumnName = "t_id")
private Teacher teacher;

//省略getter setter...

生成的表如下:

teacher表

t_id t_name
null null

student表

s_id s_name teacher_id
null null null

可以看出:
Teacher类中使用了mappedBy属性,所以在teacher表中并没有任何其他表的属性外键,因为它被Student类中的teacher属性管理了!
再看Student类中使用了@JoinColumn注解

@JoinColumn

外键注解,主要属性如下:

name:必填,外键名;
referencedColumnName:非必填,关联的表的字段名;

该注解需配合@OneToOne,@OneToMany,@ManyToOne一起使用,单独使用无效。
当然了如果在上面关系注解中使用了mappedBy,用@JoinColumn是非法的,因为mappedBy就已经表示了改类没有外键!
例子中如果不使用@JoinColumn,将会使用默认策略生成外键。

@OneToMany

一对多关联,注解的用法与@OneToOne不太一样;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Entity
public class Teacher {
@Id
private Long t_id;
private String t_name;

//省略getter setter...
}

@Entity
public class Student {
@Id
private Long s_id;
private String s_name;

@OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY)
@JoinColumn(name = "student_id")
@OrderBy("t_id DESC")
private List<Teacher> teachers;

//省略getter setter...
}

此例中在Student类中使用了@OneToMany和@JoinColumn,与上例不同的是@JoinColumn的用法,此处定义的name则是Teacher表中的外键名,因为一对多的关系,当然要在多的表里才能有外键了。
当然, @JoinColumn注解也可以省略,此时,默认策略就会生成第三张表,专门维护他们的关系。

@OrderBy

@OrderBy一般配合@OneToMany使用对集合中的数据进行排序。
值:就直接填一个属性值和排序方式ASC(升序)、DESC(降序)。

@ManyToOne

多对一,与OneToMany相对应。根据业务需求只需要在一放使用其中一个注解即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Entity
public class Teacher {
@Id
private Long t_id;
private String t_name;

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

//省略getter setter...
}

@Entity
public class Student {
@Id
private Long s_id;
private String s_name;

@OneToMany(mappedBy = "student")
private List<Teacher> teachers;

//省略getter setter...
}

@ManyToOne注解中没有mappedBy属性。
上例中可以省略掉Student中的@OneToMany,但如果需要双向关联使用,则必须改注解,同时需要标注mappedBy属性。

@ManyToMany

多对多,基本用法如出一辙。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Entity
public class Teacher {
@Id
private Long t_id;
private String t_name;

@ManyToMany
@JoinTable(name = "s_t",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "teacher_id"))
private List<Student> students;

//省略getter setter...
}

@Entity
public class Student {
@Id
private Long s_id;
private String s_name;

//省略getter setter...
}

@ManyToMany同样是支持mappedBy的,所以,如果需要双向关联,可在Student中使用mappedBy属性,此时的值应为关系表对应的类名。

@JoinTable

关联关系表的注解,主要属性如下:

name:关联关系表名;
joinColumns:主连接接表的外键;
inverseJoinColumns:被连接表的外键;

joinColumns和inverseJoinColumns的值都为@JoinColumn()注解。


双向关联:此文中双向关联并不代表在数据库中的双向外键关联,而是指对象之间的双向关联调用。