Spring Data Jpa是基于HIbernate开发的,所以建立实体建的实体和映射关系需要好好好的去了解一下,实体之间关系有:一对一、一对多(多对一)和多对多。
1.OneToOne(一对一)
一对一的情形在生活中非常罕见,比如一个居民对应一个身份证号码,一个人对应一个DNA序列等等。 我们以一个居民对应一张身份证为例,讲解Spring Data JPA如何实现一对一的映射关系。
1)创建实体类:
IdCard.java(身份证类)
package com.oracle.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
//身份证类,将来不会映射为一张身份证表。
public class IdCard implements Serializable,Cloneable {
@Id
@Column(length = 18) //中国的身份证号码是18位的。
private String pid; //身份证号码
private String province;//省份
}
Person.java(居民类)
package com.oracle.entity;
//居民类
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
//居民类应该会映射为一张居民表
public class Person implements Serializable,Cloneable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id; //注意,这是公民表的主键,不是身份证号码
private String name; //姓名
private String gender; //性别
@OneToOne
@JoinColumn(name="pid",referencedColumnName="pid")
private IdCard card;
}
测试一对一的映射关系。由于篇幅限制Person和IdCard的Repository和Service层代码省略,大家可以自行参考上节案例实现。
package com.oracle.entity;
import com.oracle.service.IdCardService;
import com.oracle.service.PersonService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
@RunWith(SpringRunner.class)
@SpringBootTest
public class OneToOneRelationshipTest {
@Resource
private PersonService personService;
@Resource
private IdCardService idCardService;
//测试一下居民和身份证之间的一对一的关联关系
@Test
public void testSavePerson(){
//生成一个身份证对象
IdCard card = new IdCard();
card.setPid("610103199910103657"); //令狐冲的身份证号码
card.setProvince("陕西省");
//生成一个居民的对象
Person p = new Person();
p.setName("令狐冲");
p.setGender("男");
p.setCard(card); //一样就体现出一对一的关联关系了。
//先存身份证,再保存居民资料
idCardService.saveIdCard(card);
personService.savePerson(p);
}
}
测试结果如下:

2.ManyToOne(多对一)
我们以一个班级有多个学生为例,讲解Spring Data JPA如何实现多对一的映射关系。
1)创建实体类 ClassRoom.java(班级类)
package com.oracle.entity;
//班级类
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.io.Serializable;
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ClassRoom implements Serializable,Cloneable {
@Id
@GeneratedValue(generator="mycid")
@GenericGenerator(name="mycid",strategy="assigned")
@Column(length = 4)
private String cid; //班级编号
private String cname; //班级的名称
}
Students.java(学生类)
package com.oracle.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Set;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity //表示这个类对应数据库中的一张表
public class Students implements Serializable,Cloneable {
//既然是表,就必须有主键
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) //使用数据库默认的主键生成策略
private int sid; //主键
@Column(length = 20) //规定学生的姓名不超过20个字符
private String sname; //姓名,默认是占用255个字符。
@Column(length = 2)
private String gender; //性别
@Column(length = 32)
private String date; //出生日期
private String school; //所在学校
private String major; //所学的专业
private boolean status; //状态 1:在籍 0:辍学
@ManyToOne
@JoinColumn(name="cid",referencedColumnName="cid")
private ClassRoom classRoom; //学生持有班级的引用。
}
测试多对一的映射关系。由于篇幅限制Students和ClassRoom的Repository和Service层代码省略,大家可以自行参考上节案例实现。
package com.oracle.entity;
import com.oracle.service.ClassRoomService;
import com.oracle.service.StudentsService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
@RunWith(SpringRunner.class)//指定Junit4使用Spring提供的测试环境
@SpringBootTest
public class ManyToOneRelationShipTest {
@Resource
private StudentsService studentsService;
@Resource
private ClassRoomService classRoomService;
@Test
//测试多对一的关联关系,多个学生对应一个班级,一个班级对应多个学生
public void testSaveStudentsAndClassRoom(){
//先创建一个班级
ClassRoom classRoom = new ClassRoom();
classRoom.setCid("C001");
classRoom.setCname("软件工程1班");
//先保存班级资料
classRoomService.saveClassRoom(classRoom);
//创建三个学生对象,让他们都属于同一个班级。
Students s1 = new Students();
s1.setSchool("武汉大学");
s1.setMajor("软件工程");
s1.setSname("张三");
s1.setGender("男");
s1.setDate("1999-10-01");
s1.setClassRoom(classRoom);
Students s2 = new Students();
s2.setSchool("武汉大学");
s2.setMajor("软件工程");
s2.setSname("李四");
s2.setGender("女");
s2.setDate("1999-09-01");
s2.setClassRoom(classRoom);
Students s3 = new Students();
s3.setSchool("武汉大学");
s3.setMajor("软件工程");
s3.setSname("王五");
s3.setGender("男");
s3.setDate("1999-12-01");
s3.setClassRoom(classRoom);
//保存三个学生资料
studentsService.save(s1);
studentsService.save(s2);
studentsService.save(s3);
}
}
测试结果如下:

3.ManyToMany(多对多)
我们以生活中一个老师教多个学生,一个学生有多个老师为例,讲解Spring Data JPA如何实现多对多的映射关系。
1)创建实体 Teachers.java(教师类)
package com.oracle.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.io.Serializable;
//教师表
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teachers implements Serializable,Cloneable {
@Id
@GeneratedValue(generator="mytid")
@GenericGenerator(name="mytid",strategy="assigned")
@Column(length = 4)
private String tid; //教师编号
private String tname; //教师姓名
}
Students.java(学生类)
package com.oracle.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Set;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity //表示这个类对应数据库中的一张表
public class Students implements Serializable,Cloneable {
//既然是表,就必须有主键
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) //使用数据库默认的主键生成策略
private int sid; //主键
@Column(length = 20) //规定学生的姓名不超过20个字符
private String sname; //姓名,默认是占用255个字符。
@Column(length = 2)
private String gender; //性别
@Column(length = 32)
private String date; //出生日期
private String school; //所在学校
private String major; //所学的专业
private boolean status; //状态 1:在籍 0:辍学
@ManyToOne
@JoinColumn(name="cid",referencedColumnName="cid")
private ClassRoom classRoom;
//学生持有教师的集合
@ManyToMany
//通过中间表来维护多多的关系。表名叫teachers_students
@JoinTable(name = "teachers_students",
joinColumns = {
@JoinColumn(name = "sid") },
inverseJoinColumns = {@JoinColumn(name = "tid") }
)
private Set<Teachers> teachers; //学生持有的教师集合
}
测试多对多的映射关系。由于篇幅限制Students和Teachers的Repository和Service层代码省略,大家可以自行参考上节案例实现。
package com.oracle.entity;
import com.oracle.service.ClassRoomService;
import com.oracle.service.StudentsService;
import com.oracle.service.TeachersService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Set;
@RunWith(SpringRunner.class)//指定Junit4使用Spring提供的测试环境
@SpringBootTest
public class ManyToManyRelationShipTest {
@Resource
private StudentsService studentsService;
@Resource
private TeachersService teachersService;
@Resource
private ClassRoomService classRoomService;
@Test
public void testSaveStudentsAndTeachers() {
//先创建一个班级
ClassRoom classRoom = new ClassRoom();
classRoom.setCid("C001");
classRoom.setCname("软件工程1班");
//先保存班级
classRoomService.saveClassRoom(classRoom);
Students s1 = new Students();
s1.setSchool("武汉大学");
s1.setMajor("软件工程");
s1.setSname("张三");
s1.setGender("男");
s1.setDate("1999-10-01");
s1.setClassRoom(classRoom);
Students s2 = new Students();
s2.setSchool("武汉大学");
s2.setMajor("软件工程");
s2.setSname("李四");
s2.setGender("女");
s2.setDate("1999-09-01");
s2.setClassRoom(classRoom);
Students s3 = new Students();
s3.setSchool("武汉大学");
s3.setMajor("软件工程");
s3.setSname("王五");
s3.setGender("男");
s3.setDate("1999-12-01");
s3.setClassRoom(classRoom);
//创建三个教师对象
Teachers t1 = new Teachers();
t1.setTid("T001");
t1.setTname("陈老师");
Teachers t2 = new Teachers();
t2.setTid("T002");
t2.setTname("刘老师");
Teachers t3 = new Teachers();
t3.setTid("T003");
t3.setTname("赵老师");
//保存教师
teachersService.saveTeachers(t1);
teachersService.saveTeachers(t2);
teachersService.saveTeachers(t3);
Set<Teachers> set1 = new HashSet<Teachers>();
set1.add(t1);
set1.add(t2);
set1.add(t3);
Set<Teachers> set2 = new HashSet<Teachers>();
set2.add(t1);
set2.add(t2);
Set<Teachers> set3 = new HashSet<Teachers>();
set3.add(t2);
set3.add(t3);
//设置三个学生的教师集合
s1.setTeachers(set1);
s2.setTeachers(set2);
s3.setTeachers(set3);
//保存学生
studentsService.save(s1);
studentsService.save(s2);
studentsService.save(s3);
}
}
测试结果如下:
