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);
}
}
此时结果: