Bootstrap

mybatis的多对一、一对多的用法

目录

1、使用VO聚合对象(可以解决这两种情况)

多对一:

一对多:

2、非聚合的多对一做法:

3、非聚合的一对多做法:


1、使用VO聚合对象(可以解决这两种情况)

当我需要多对一、一对多时,可以创建VO聚合对象。

例如:学生类和老师类,会出现多对一、一对多的情况。此时创建一个聚合类,里面包含所需要的学生类和老师类的属性。并先查询出前面的内容,再根据前面的内容查询出后面的内容。

多对一:

数据库设计,学生表中有一个tid来匹配老师id:

 

在学生类和老师类后,再创建出一个聚合类:

@Data
public class Student {
    private Integer id;
    private String username;
    private Integer tid;
}
@Data
public class Teacher {
    private Integer id;
    private String username;
}
@Data
public class StudentAndTeacher {
    private Integer id;
    private String username;
    private Teacher teacher;
}

写出查询所有学生和根据学生类里的tid查询老师: 

@Mapper
public interface AllMapper {
    List<Student> AllStudent();
    Teacher AllTeacherByTid(Integer tid);
}
    <select id="AllStudent" resultType="com.example.demo.entity.Student">
        select * from student;
    </select>

    <select id="AllTeacherByTid" resultType="com.example.demo.entity.Teacher">
        select * from teacher where id=#{tid};
    </select>

通过聚合类,把这两个查询到的内容聚合到一起:

    @Test
    public void AllStudent() {
        List<Student> students = allMapper.AllStudent();
        for (Student student : students) {
            StudentAndTeacher studentAndTeacher = new StudentAndTeacher();
            studentAndTeacher.setId(student.getId());
            studentAndTeacher.setUsername(student.getUsername());
            studentAndTeacher.setTeacher(allMapper.AllTeacherByTid(student.getTid()));
            System.out.println(studentAndTeacher);
        }
    }

结果如下:

一对多:

学生类和老师类一样,但是聚合类不一样,因为现在的主体是老师,而不是学生。

@Data
public class Student {
    private Integer id;
    private String username;
    private Integer tid;
}
@Data
public class Teacher {
    private Integer id;
    private String username;
}
@Data
public class TeacherAndStudent {
    private Integer id;
    private String username;
    private List<Student> studentList;
}

写出查询所有老师和根据老师的id去学生表里查对应tid的学生: 

@Mapper
public interface AllMapper {
    List<Teacher> AllTeacher();
    List<Student> AllStudentById(Integer id);
}
    <select id="AllTeacher" resultType="com.example.demo.entity.Teacher">
        select * from teacher;
    </select>

    <select id="AllStudentById" resultType="com.example.demo.entity.Student">
        select * from student where tid=#{id};
    </select>

通过聚合类,把这两个查询到的内容聚合到一起:

    @Test
    public void AllTeacher() {
        List<Teacher> Teachers = allMapper.AllTeacher();
        for (Teacher teacher : Teachers) {
            List<Student> students = allMapper.AllStudentById(teacher.getId());
            TeacherAndStudent studentAndTeacher = new TeacherAndStudent();
            studentAndTeacher.setId(teacher.getId());
            studentAndTeacher.setUsername(teacher.getUsername());
            studentAndTeacher.setStudentList(students);
            System.out.println(studentAndTeacher);
        }
    }

结果如下:

2、非聚合的多对一做法:

知识点:association标签是用在多对一时,当一个类中有其他类作为该类的属性时,要用到这个标签。

此时的Student类中有一个属性是Teacher类:

@Data
public class Student {
    private Integer id;
    private String username;
    private Teacher teacher;
}
@Data
public class Teacher {
    private Integer id;
    private String username;
}
@Mapper
public interface AllMapper {
    List<Student> AllStudent();
}

这里用resultMap来匹配。 

要注意两点:

1、result 标签里的property对应的是java类的属性名,column对应的是select 标签里查询出来的字段名。并且要注意,若多个表的字段名相同,必须要用别名区分,并在column中写上别名而非字段名。

2、association 标签中,property对应的是Student类中的teacher属性,类型为Student类,这里的类型用javaType而不是Type。

    <select id="AllStudent" resultMap="StudentAndTeacher">
        select s.id sid, s.username susername, t.id tid, t.username tusername
        from student s, teacher t
        where s.tid = t.id;
    </select>
    <resultMap id="StudentAndTeacher" type="com.example.demo.entity.Student">
        <result property="id" column="sid"></result>
        <result property="username" column="susername"></result>
        <association property="teacher" javaType="com.example.demo.entity.Teacher">
            <result property="id" column="tid"></result>
            <result property="username" column="tusername"></result>
        </association>
    </resultMap>
 @Test
    public void StudentAndTeacher() {
        List<Student> students = allMapper.AllStudent();
        for (Student student : students) {
            System.out.println(student);
        }
    }

结果如下:

3、非聚合的一对多做法:

知识点:collection标签是用在一对多时,当一个类中有其他类集合作为该类的属性时,要用到这个标签。

此时的Teacher类中有一个属性是List<Student>:

@Data
public class Student {
    private Integer id;
    private String username;
    private Integer tid;
}
@Data
public class Teacher {
    private Integer id;
    private String username;
    private List<Student> students;
}
@Mapper
public interface AllMapper {
    List<Teacher> AllTeacher();
}

这里用resultMap来匹配。 

要注意两点:

1、result 标签里的property对应的是java类的属性名,column对应的是select 标签里查询出来的字段名。并且要注意,若多个表的字段名相同,必须要用别名区分,并在column中写上别名而非字段名。

2、collection标签中,property对应的是Teacher类中的students属性,类型为List,这里的类型用javaType而不是Type,ofType指的是List的泛型。

    <select id="AllTeacher" resultMap="TeacherAndStudent">
        select s.id sid, s.username susername, s.tid stid, t.id tid, t.username tusername
        from student s, teacher t
        where s.tid = t.id;
    </select>
    <resultMap id="TeacherAndStudent" type="com.example.demo.entity.Teacher">
        <result property="id" column="tid"></result>
        <result property="username" column="tusername"></result>
        <collection property="students" javaType="List"        
         ofType="com.example.demo.entity.Student">
            <result property="id" column="sid"></result>
            <result property="username" column="susername"></result>
            <result property="tid" column="stid"></result>
        </collection>
    </resultMap>
    @Test
    public void StudentAndTeacher() {
        List<Teacher> teachers = allMapper.AllTeacher();
        for (Teacher teacher : teachers) {
            System.out.println(teacher);
        }
    }

此时结果:

;