Use Hibernate to store one-to-many object relationships

There is often a relationship between object entities in life. There is a one-to-one, one-to-many, and many-to-many relationship. For example, if there are multiple students in a course class, it is a one-to-many relationship. In the database, you can add a foreign key to the student table to point to the class id to indicate that the student contains multiple students. Correspondingly, in Java, you can create Course and Student to represent the class and student. What is the relationship between the two?

The following shows the courses table and students table in the database

   

One-to-many mapping

The first way is one-to-many mapping, for example, to create a mapping from class ("one")-> student ("many"). You can add a Set collection in the Course class to save multiple Student objects, and set Course to point to Student in hibernate.

Add the Hibernate database mapping to the two classes in IDEA, and automatically generate CourseEntity class and StudentEntity class files and the corresponding hbm.xml mapping file, and complete the registration in the hibernate.cfg.xml file. After that, manually add the Set property students and its get / set method in CourseEntity

public class CoursesEntity {
    private int id;
    private String name;
    private Integer hours;
    private Set<StudentEntity> students=new HashSet<StudentEntity>();
    
    ......

    public Set<StudentEntity> getStudents() {
        return students;
    }

    public void setStudents(Set<StudentEntity> students) {
        this.students = students;
    }

Then you need to modify the CourseEntity.hbm.xml file, add the set attribute students to it, specify its corresponding data table and the foreign key associated with the courses of this data table, and the Java entity class corresponding to this attribute

    <class name="entity.CoursesEntity" table="courses" schema="test">
        <id name="id" column="id"/>
        <property name="name" column="name"/>
        <property name="hours" column="hours"/>
        <set name="students" table="students">              <!--配置students集合对应的表-->
            <key column="course_id"></key>                  <!--表中对应的外键-->
            <one-to-many class="entity.StudentEntity"/>     <!--对应的Java类-->
        </set>
    </class>

Then create a course course object in the test method, and two student objects s1, s2, and call Set add () in the course students collection to add two student objects, and finally save these objects in the database. Note that the Junit test unit is still used here, so the creation and shutdown of session and factory are completed in the previous setup and tearDown.

    @Test
    void testCourse(){
        //创建课程和学生对象
        CoursesEntity course=new CoursesEntity(2,"Data Structure",72);
        StudentEntity s1=new StudentEntity(1003,"小明",15);
        StudentEntity s2=new StudentEntity(1004,"小花",14);
        //在课程的students的Set集合中添加两个学生对象
        course.getStudents().add(s1);
        course.getStudents().add(s2);
        //保存课程和学生对象到数据库
        session.save(course);
        session.save(s1);
        session.save(s2);
    }

Looking at the database, it can be seen that the corresponding course has been added to the course table, and not only two students have been added to the students table, but also the foreign key course_id points to the corresponding course id

   

It is also very convenient to view the data. You can traverse the selected students through the Set collection returned by course, and hibernate will automatically go to the students table to extract the corresponding student information

     @Test
    void findCourse() {
        CoursesEntity course = session.load(CoursesEntity.class, 2);
        System.out.println("课程名称:"+course.getName());
        //通过course返回学生Set集合遍历学生信息
        Set<StudentEntity> students = course.getStudents();
        System.out.println("课程学生:");
        for (StudentEntity student : students)
            System.out.print(student.getId() + ':' + student.getName());
    }

Delete a student from the course by calling the remove () method of Set, the database will automatically modify the foreign key of the student course_id to null

CoursesEntity course = session.load(CoursesEntity.class, 2);
Set<StudentEntity> students = course.getStudents();            //获取课程学生的Set集合
StudentEntity s=session.load(StudentEntity.class,1003);        //获取指定学生对象
//从选课列表删除指定学生
students.remove(s);         
session.save(s);        //保存操作

Bidirectional mapping

In addition to configuring the mapping from Course to Student, you can also configure the mapping from Student to Course. This achieves a two-way mapping between the two object types. The mapping of Student-> Course is as follows:

First add the variables course and get / set methods that represent the attributes of the course in the StudentEntity class

public class StudentEntity {
    private int id;
    private String name;
    private Integer age;
    private Address address;
    private CoursesEntity course;    //添加表示所在课程的属性
    
    ......

    public CoursesEntity getCourse() {
        return course;
    }

    public void setCourse(CoursesEntity course) {
        this.course = course;
    }

Then configure the "multiple" hbm.xml file, name is the variable name, class is the class pointed to, and column is the foreign key in the data table

    <class name="entity.StudentEntity" table="students" schema="test">
        <id name="id" column="id"/>
        <property name="name" column="Name"/>
        <property name="age" column="Age"/>
        <component name="address" class="entity.Address">
            <property name="city" column="city"/>
            <property name="street" column="street"/>
        </component>
        <!--配置Student指向Course的映射-->
        <many-to-one name="course" class="entity.CoursesEntity" column="course_id"/>
    </class>

Next, create Course and Student objects in the code and perform two-way mapping

    @Test
    void testCourse() {
        //创建课程和学生对象
        CoursesEntity course = new CoursesEntity(2, "Data Structure", 72);
        StudentEntity s1 = new StudentEntity(1003, "小明", 15);
        StudentEntity s2 = new StudentEntity(1004, "小花", 14);

        //添加Course --> Student映射
        course.getStudents().add(s1);
        course.getStudents().add(s2);
        //添加Student --> Course映射
        s1.setCourse(course);
        s2.setCourse(course);

        //保存课程和学生对象到数据库
        session.save(course);
        session.save(s1);
        session.save(s2);
    }

Maintain two-way mapping : Through the above operation, the two-way mapping of the data table is realized, but looking at the HIbernate execution statement as shown below, two update operations are performed after two insert operations on the students table. This is because Course performs a force insert operation when maintaining a one-to-many relationship, and then a student performs an update operation when maintaining a many-to-one relationship. Such an operation is unnecessary and affects execution efficiency. Obviously this is due to the fact that both parties are maintaining a one-to-many relationship, so we hope that only one party maintains the one-to-many relationship. Set the inverse property of set in the Course configuration file to false, which means that the relationship is "many" That party will maintain.

Hibernate: insert into courses (name, hours, id) values (?, ?, ?)
Hibernate: insert into students (Name, Age, city, street, course_id, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into students (Name, Age, city, street, course_id, id) values (?, ?, ?, ?, ?, ?)
Hibernate: update students set course_id=? where id=?
Hibernate: update students set course_id=? where id=?

Cascading operation : When saving objects through session, we not only execute session.save (course), but also execute session.save (s1) to save students. Student is already included in the Course object, and should be automatically saved together. Instead of saving it manually, this requires cascading operations to set it up. You can configure the set in the Course configuration file, set the cascade properties as follows

Set the inverse and cascade as follows:

    <class name="entity.CoursesEntity" table="courses" schema="test">
        <id name="id" column="id"/>
        <property name="name" column="name"/>
        <property name="hours" column="hours"/>
        <!--对inverse、cascade属性进行设置-->
        <set name="students" table="students" inverse="false" cascade="save-update">
            <key column="course_id"></key> 
            <one-to-many class="entity.StudentEntity"/>
        </set>
    </class>
Published 124 original articles · Like 65 · Visit 130,000+

Guess you like

Origin blog.csdn.net/theVicTory/article/details/104542484