mybatis学习——多对一和一对多查询
首先先来说明一下数据库,数据库有两张表student表和teacher表:
student表如下:
teacher表如下:
两张表的关系:多个学生关联一位老师(多对一)
*其中tid是外键
需要sql语句的朋友可以在这里取:
CREATE TABLE `teacher`( `id` INT(10) NOT NULL, `name` VARCHAR(30) DEFAULT NULL, PRIMARY KEY(`id`) )ENGINE=INNODB DEFAULT CHARSET=utf8 INSERT INTO teacher(`id`,`name`) VALUES (1,'秦老师'); CREATE TABLE `student`( `id` INT(10) NOT NULL, `name` VARCHAR(30) DEFAULT NULL, `tid` INT(10) DEFAULT NULL, PRIMARY KEY(`id`), KEY `fktid` (`tid`), CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`) )ENGINE=INNODB DEFAULT CHARSET=utf8 INSERT INTO `student`(`id`,`name`,`tid`) VALUES ('1','小明','1'); INSERT INTO `student`(`id`,`name`,`tid`) VALUES ('2','小红','1'); INSERT INTO `student`(`id`,`name`,`tid`) VALUES ('3','小张','1'); INSERT INTO `student`(`id`,`name`,`tid`) VALUES ('4','小李','1'); INSERT INTO `student`(`id`,`name`,`tid`) VALUES ('5','小王','1'); SELECT * FROM student; SELECT * FROM teacher;
下面进入正题:
一、多对一
1.编写pojo类
注意:在“多”这一边添加一个“一”的对象作为属性。例如:在student实体类中添加一个属性 Teacher teacher;
@Data public class Student { private int id; private String name; //学生需要关联一个老师 private Teacher teacher; }
@Data public class Teacher { private int id; private String name; }
注意:@Data是一个注解,使用这个注解可以自动帮我们引入get()、 set()、 toString()等方法。这个注解来自lombok,要使用这个注解首先要安装lombok插件并导入相关jar包。
2.编写接口类
public interface StudentMapper { public List<Student> getStudent(); }
3.编写映射文件
这里有两种方法,按照查询嵌套处理和按照结果嵌套处理
方式一:按照查询嵌套处理
思路:我们先查询所有的学生,然后根据查询出来的学生的tid再去查询对应的老师的信息,代码如下所示
<?xml version="1.0" encoding="GBK" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.orggetStudent//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.kuang.dao.StudentMapper"> <select id="getStudent" resultMap="StudentTeacher"> SELECT * FROM student </select> <resultMap id="StudentTeacher" type="Student"> <result property="id" column="id"/> <result property="name" column="name"/> <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/> </resultMap>
<select id="getTeacher" resultType="Teacher">
SELECT * FROM teacher where id = #{tid}
</select>
</mapper>
注意:
●用来指定实体类中属性的类型。还不懂的话,那就再细说一点:由于上边代码<association >标签中properties的值是teacher,实体类Student中teacher属性的类型是Teacher,所以javaType="Teacher"
●在上边代码中<resultMap>标签里简单的属性我们可以用<result>标签去映射,但是复杂的属性就用不了了,那怎么结局复杂属性的映射怎么解决呢?有两种情况:
①.复杂属性是对象:用association
②.复杂属性是集合,用collection
映射过程图解:
方式二:按照结果嵌套处理
这种方法比较简单,只要对比上一种方法你就能明白了,这里就不详细赘述了。
映射文件代码如下:
<!--方式二-->
<select id="getStudent2" resultMap="StudentTeacher2">
SELECT s.id AS sid,s.name AS sname,t.id AS tid,t.name AS tname
FROM student s,teacher t
WHERE s.tid = t.id
</select>
<resultMap id="StudentTeacher2" type="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
</association>
</resultMap>
注意:
●select语句中给字段区别名那里不能省略,不然查询结果会出错。出错的原因我现在不知道,有知道的朋友欢迎在下边评论,不胜感谢!
二、一对多
1.编写pojo类
*tip:在“一”这一边添加一个“多”的对象的泛型集合作为属性。例如:在Teacher 实体类中添加一个属性 List<Student> students;
@Data public class Teacher { private int id; private String name; //一个老师拥有多个学生 private List<Student> students; }
@Data
public class Student {
private int id;
private String name;
private int tid;
}
注意:@Data是一个注解,使用这个注解可以自动帮我们引入get()、 set()、 toString()等方法。这个注解来自lombok,要使用这个注解首先要安装lombok插件并导入相关jar包。
2.编写接口类
public interface TeacherMapper {
//获取指定老师下的所有学生及老师的信息
Teacher getTeacher(@Param("tid") int id);
}
3.编写映射文件
这里有两种方法,按照查询嵌套处理和按照结果嵌套处理
方式一:按照查询嵌套处理
思路:我们先根据id查询所有的老师,然后根据查询出来的老师的id再去查询对应的学生的信息,代码如下所示
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.kuang.dao.TeacherMapper"> <select id="getTeacher" resultMap="TeacherStudent"> SELECT * FROM teacher WHERE id = #{tid} </select> <resultMap id="TeacherStudent" type="Teacher"> <result property="id" column="id"/> <result property="name" column="name"/> <collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id"/> </resultMap> <select id="getStudentByTeacherId" resultType="Student"> SELECT * FROM student WHERE tid = #{tid} </select> </mapper>
注意:
●javaType:用来指定实体类中属性的类型。还不懂的话,那就再细说一点:由于上边代码<collection >标签中properties的值是students,实体类Teacher中students属性的类型是一个泛型列表ArrayList,所以javaType="ArrayList"
●ofType:用来指定映射到集合中的pojo类型,泛型中的约束类型。
方式二:按照结果嵌套处理
<select id="getTeacher" resultMap="TeacherStudent"> SELECT s.id sid,s.name sname,t.name tname,t.id tid FROM student s,teacher t WHERE t.id = #{tid} AND s.tid = t.id </select> <resultMap id="TeacherStudent" type="Teacher"> <result column="tid" property="id"/> <result column="tname" property="name"/> <collection property="students" javaType="ArrayList" ofType="Student"> <result column="sid" property="id"/> <result column="sname" property="name"/> <result column="tid" property="tid"/> </collection> </resultMap>