← 返回首页
SpringBoot基础教程(十五)
发表时间:2020-10-24 22:07:38
实体之间的关联关系

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);
    }
}

测试结果如下: