单向多对多映射

多对多关系是关系数据库中两个表之间的一种关系,该关系中第一个表中的一个行可以与第二个表中的一个或多个行相关。第二个表中的一个行也可以与第一个表中的一个或多个行相关。

下面将通过教师和学生的关系来演示 OpenJPA 中怎样实现多对多关系映射,在 OpenJPA 中,使用 @ManyToMany 注解来指定多对多关系。

表结构设计

多对多关系的表结构设计和一对多关系表结构是一致的,OpenJPA 中使用的是中间表来维护关系。数据表结构图如下:

上图的中间表用来保存教师和学生关系。

对象设计

(1)教师表对应的 Teacher 对象,代码如下:

@Data
@Entity
@Table
public class Teacher {
    @Id
    @GeneratedValue
    private int id;

    @Column
    private String name;

    @ManyToMany
    private List<Student> studentList;
}

(2)学生表对应的 Student 对象,代码如下:

@Data
@Entity
@Table
public class Student {
    @Id
    @GeneratedValue
    private int id;

    @Column
    private String name;

    // 放弃多对多关系维护,让 Teacher 维护多对多关系
    @ManyToMany(mappedBy = "studentList")
    private List<Teacher> teacherList;
}

上图中,使用 mappedBy 属性放弃 Student 方对关系的维护。如果不进行 mappedBy 配置,则会创建两张关系表,分别有 Student 和 Teacher 进行维护。

示例代码

(1)教师实体对象,代码如下:

@Data
@Entity
@Table
public class Teacher {
    @Id
    @GeneratedValue
    private int id;

    @Column
    private String name;

    @ManyToMany
    private List<Student> studentList;
}

(2)学生实体对象,代码如下:

@Data
@Entity
@Table
public class Student {
    @Id
    @GeneratedValue
    private int id;

    @Column
    private String name;

    // 放弃多对多关系维护,让 Teacher 维护多对多关系
    @ManyToMany(mappedBy = "studentList")
    private List<Teacher> teacherList;
}

(3)客户端代码

import com.alibaba.fastjson.JSONObject;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.TypedQuery;
import java.util.ArrayList;
import java.util.List;

/**
 * 双向多对多映射
 * @author Administrator 2021-9-10 13:37:37
 */
public class Demo {
    /** 持久化单元名称 */
    private static final String NAME = "demo_manytomany";

    private static void insertData(EntityManager em) {
        try {
            em.getTransaction().begin();

            // 教师
            Teacher teacher1 = new Teacher();
            teacher1.setName("教师1");

            Teacher teacher2 = new Teacher();
            teacher2.setName("教师2");

            List<Teacher> teacherList = new ArrayList<Teacher>();
            teacherList.add(teacher1);
            teacherList.add(teacher2);

            // 学生
            Student student1 = new Student();
            student1.setName("学生1");

            Student student2 = new Student();
            student2.setName("学生2");

            List<Student> studentList = new ArrayList<Student>();
            studentList.add(student1);
            studentList.add(student2);

            teacher1.setStudentList(studentList);
            teacher2.setStudentList(studentList);

            student1.setTeacherList(teacherList);
            student2.setTeacherList(teacherList);

            // 持久化
            em.persist(student1);
            em.persist(student2);
            em.persist(teacher1);
            em.persist(teacher2);

            em.getTransaction().commit();
        } finally {
            em.close();
        }
    }

    private static void selectData(EntityManager em) {
        try {
            em.getTransaction().begin();
            // 查询教师信息
            TypedQuery<Teacher> teacherTypedQuery = em.createQuery(
                    "select t from Teacher t", Teacher.class);
            for(Teacher teacher : teacherTypedQuery.getResultList()) {
                System.out.println("teacher_id=" + teacher.getId());
                System.out.println("teacher_name=" + teacher.getName());
                System.out.println("teacher_students=" +
                        JSONObject.toJSONString(teacher.getStudentList()));
            }

            // 查询学生信息
            TypedQuery<Student> studentTypedQuery = em.createQuery(
                    "select s from Student s", Student.class);
            for(Student student : studentTypedQuery.getResultList()) {
                System.out.println("student_id=" + student.getId());
                System.out.println("student_name=" + student.getName());
                System.out.println("student_teacher=" +
                        JSONObject.toJSONString(student.getTeacherList()));
            }

            em.getTransaction().commit();
        } finally {
            em.close();
        }
    }

    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory(NAME);
        // 插入数据
        insertData(emf.createEntityManager());
        // 查询数据
        selectData(emf.createEntityManager());
        emf.close();
        System.out.println("finished.");
    }

}

执行上面客户端代码后,输出的SQL如下:

-- 创建表格和索引
CREATE TABLE OPENJPA_SEQUENCE_TABLE (ID TINYINT NOT NULL, SEQUENCE_VALUE BIGINT, PRIMARY KEY (ID)) ENGINE = innodb
CREATE TABLE Student (id INTEGER NOT NULL, name VARCHAR(255), PRIMARY KEY (id)) ENGINE = innodb
CREATE TABLE Teacher (id INTEGER NOT NULL, name VARCHAR(255), PRIMARY KEY (id)) ENGINE = innodb
CREATE TABLE Teacher_Student (TEACHERLIST_ID INTEGER, STUDENTLIST_ID INTEGER) ENGINE = innodb
CREATE INDEX I_TCHRDNT_ELEMENT ON Teacher_Student (STUDENTLIST_ID)
CREATE INDEX I_TCHRDNT_TEACHERLIST_ID ON Teacher_Student (TEACHERLIST_ID)
-- 使用序列表生成ID值
SELECT SEQUENCE_VALUE FROM OPENJPA_SEQUENCE_TABLE WHERE ID = ? FOR UPDATE [params=?]
INSERT INTO OPENJPA_SEQUENCE_TABLE (ID, SEQUENCE_VALUE) VALUES (?, ?) [params=?, ?]
SELECT SEQUENCE_VALUE FROM OPENJPA_SEQUENCE_TABLE WHERE ID = ? FOR UPDATE [params=?]
UPDATE OPENJPA_SEQUENCE_TABLE SET SEQUENCE_VALUE = ? WHERE ID = ? AND SEQUENCE_VALUE = ? [params=?, ?, ?]
SELECT SEQUENCE_VALUE FROM OPENJPA_SEQUENCE_TABLE WHERE ID = ? FOR UPDATE [params=?]
UPDATE OPENJPA_SEQUENCE_TABLE SET SEQUENCE_VALUE = ? WHERE ID = ? AND SEQUENCE_VALUE = ? [params=?, ?, ?]
-- 插入学生信息
INSERT INTO Student (id, name) VALUES (?, ?) [params=?, ?]
INSERT INTO Student (id, name) VALUES (?, ?) [params=?, ?]
-- 插入教师信息
INSERT INTO Teacher (id, name) VALUES (?, ?) [params=?, ?]
INSERT INTO Teacher (id, name) VALUES (?, ?) [params=?, ?]
-- 插入教师和学生关系信息
INSERT INTO Teacher_Student (TEACHERLIST_ID, STUDENTLIST_ID) VALUES (?, ?) [params=?, ?]
INSERT INTO Teacher_Student (TEACHERLIST_ID, STUDENTLIST_ID) VALUES (?, ?) [params=?, ?]
INSERT INTO Teacher_Student (TEACHERLIST_ID, STUDENTLIST_ID) VALUES (?, ?) [params=?, ?]
INSERT INTO Teacher_Student (TEACHERLIST_ID, STUDENTLIST_ID) VALUES (?, ?) [params=?, ?]
-- 查询教师信息
SELECT t0.id, t0.name FROM Teacher t0

SELECT t1.id, t1.name FROM Teacher_Student t0 INNER JOIN Student t1 ON t0.STUDENTLIST_ID = t1.id WHERE t0.TEACHERLIST_ID = ? [params=?]
SELECT t1.id, t1.name FROM Teacher_Student t0 INNER JOIN Teacher t1 ON t0.TEACHERLIST_ID = t1.id WHERE t0.STUDENTLIST_ID = ? [params=?]
SELECT t1.id, t1.name FROM Teacher_Student t0 INNER JOIN Teacher t1 ON t0.TEACHERLIST_ID = t1.id WHERE t0.STUDENTLIST_ID = ? [params=?]
SELECT t1.id, t1.name FROM Teacher_Student t0 INNER JOIN Student t1 ON t0.STUDENTLIST_ID = t1.id WHERE t0.TEACHERLIST_ID = ? [params=?]

teacher_id=51
teacher_name=教师1
teacher_students=[{"id":1,"name":"学生1","teacherList":[{"id":51,"name":"教师1","studentList":[{"$ref":"$[0]"},{"id":2,"name":"学生2","teacherList":[{"$ref":"$[0].teacherList[0]"},{"id":52,"name":"教师2","studentList":[{"$ref":"$[0]"},{"$ref":"$[0].teacherList[0].studentList[1]"}]}]}]},{"$ref":"$[0].teacherList[0].studentList[1].teacherList[1]"}]},{"$ref":"$[0].teacherList[0].studentList[1]"}]

teacher_id=52
teacher_name=教师2
teacher_students=[{"id":1,"name":"学生1","teacherList":[{"id":51,"name":"教师1","studentList":[{"$ref":"$[0]"},{"id":2,"name":"学生2","teacherList":[{"$ref":"$[0].teacherList[0]"},{"id":52,"name":"教师2","studentList":[{"$ref":"$[0]"},{"$ref":"$[0].teacherList[0].studentList[1]"}]}]}]},{"$ref":"$[0].teacherList[0].studentList[1].teacherList[1]"}]},{"$ref":"$[0].teacherList[0].studentList[1]"}]

-- 查询学生信息
SELECT t0.id, t0.name FROM Student t0
student_id=1
student_name=学生1
student_teacher=[{"id":51,"name":"教师1","studentList":[{"id":1,"name":"学生1","teacherList":[{"$ref":"$[0]"},{"id":52,"name":"教师2","studentList":[{"$ref":"$[0].studentList[0]"},{"id":2,"name":"学生2","teacherList":[{"$ref":"$[0]"},{"$ref":"$[0].studentList[0].teacherList[1]"}]}]}]},{"$ref":"$[0].studentList[0].teacherList[1].studentList[1]"}]},{"$ref":"$[0].studentList[0].teacherList[1]"}]

student_id=2
student_name=学生2
student_teacher=[{"id":51,"name":"教师1","studentList":[{"id":1,"name":"学生1","teacherList":[{"$ref":"$[0]"},{"id":52,"name":"教师2","studentList":[{"$ref":"$[0].studentList[0]"},{"id":2,"name":"学生2","teacherList":[{"$ref":"$[0]"},{"$ref":"$[0].studentList[0].teacherList[1]"}]}]}]},{"$ref":"$[0].studentList[0].teacherList[1].studentList[1]"}]},{"$ref":"$[0].studentList[0].teacherList[1]"}]
说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号