mybatis学习9-一对一,一对多查询
mysql
CREATE DATABASE `mybatis`; USE `mybatis`; CREATE TABLE `teacher` ( `id` INT(10) auto_increment PRIMARY KEY, `name` VARCHAR(30) DEFAULT NULL ) ENGINE=INNODB DEFAULT CHARSET=utf8 INSERT INTO teacher(`name`) VALUES ('秦老师'); INSERT INTO teacher(`name`) VALUES ('周老师'); CREATE TABLE `student` ( `id` INT(10) auto_increment PRIMARY KEY, `name` VARCHAR(30) DEFAULT NULL, `tid` INT(10) DEFAULT NULL, KEY `fktid` (`tid`), CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`) ) ENGINE=INNODB DEFAULT CHARSET=utf8 INSERT INTO `student` (`name`, `tid`) VALUES ('小明', '1'); INSERT INTO `student` (`name`, `tid`) VALUES ('小红', '1'); INSERT INTO `student` (`name`, `tid`) VALUES ('小张', '1'); INSERT INTO `student` (`name`, `tid`) VALUES ('小李', '1'); INSERT INTO `student` (`name`, `tid`) VALUES ('小王', '1'); INSERT INTO `student` (`name`, `tid`) VALUES ('大明', '2'); INSERT INTO `student` (`name`, `tid`) VALUES ('大红', '2'); INSERT INTO `student` (`name`, `tid`) VALUES ('大张', '2'); INSERT INTO `student` (`name`, `tid`) VALUES ('大李', '2'); INSERT INTO `student` (`name`, `tid`) VALUES ('大王', '2');
一对一(一对多)
学生类
import lombok.Data;//lombook插件 @Data//GET,SET,ToString,有参,无参构造 public class Student { private int id; private String name; private Teacher teacher; @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
老师类
import lombok.Data;//lombook插件
@Data public class Teacher { private int id; private String name; }
学生类的代理接口
public interface StudentMapper { List<Student> listStudent();//获取学生及其老师的信息 List<Student> listStudent2();//获取学生及其老师的信息 }
查询学生的同时查询出他的老师是哪个,可以直接通过一个语句直接查询到结果,但是这样是封装不到pojo对象的
select * from student s,teacher t
where s.tid = t.id
可以通过resultMap进行结果映射,有两种方法
1.按照结果嵌套处理
association关联属性
property:类的属性名
column:数据库中表的列名,或者列的别名,这里用的就是别名(select语句中定义了别名)
javaType:属性的类型
<?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.cong.dao.StudentMapper"> <!--直接查询出结果,进行结果集的映射--> <resultMap id="studentMap" type="student"> <id property="id" column="sid"/> <result property="name" column="sname"/> <!--关联对象property 关联对象在Student实体类中的属性--> <association property="teacher" javaType="teacher"> <id property="id" column="tid"/> <result property="name" column="tname"/> </association> </resultMap> <select id="listStudent" resultMap="studentMap"> select s.id sid,s.name sname,t.id tid,t.name tname from student s,teacher t where s.tid = t.id </select> </mapper>
2.还有一种,是按照查询进行嵌套处理的
根据数据库中学生表的tid获取老师的信息,在数据库中一般用关联查询
做一个结果集映射studentMap2,它的结果类型是Student
学生类中包含一个老师的属性teacher,对应数据库中的tid
其中select * from teacher where id = #{tid}是根据 select * from student 传递过来的tid进行查询的,
只有一个参数,所以这个#{tid}可以是任意值,比如#{aaaaaa},#{tttttt},都行
<select id="listStudent2" resultMap="studentMap2"> select * from student </select> <select id="getTeacher" resultType="teacher"> select * from teacher where id = #{tid} </select> <resultMap id="studentMap2" type="student"> <association property="teacher" column="tid" javaType="teacher" select="getTeacher"/> </resultMap>
如果是多个参数的话,是通过键值对的形式进行传递的
association中column多参数配置: column="{key=value,key=value}" ,key是传给下个sql的取值名称,value是片段一中sql查询的字段名。
比如
<resultMap id="StudentTeacher" type="Student"> <association property="teacher" column="{id=tid,name=tid}" javaType="Teacher" select="getTeacher"/> </resultMap> <select id="getTeacher" resultType="teacher"> select * from teacher where id = #{id} and name = #{name} </select>
测试类
public class Test1 { @Test public void test1() { SqlSession sqlSession = MybatisUtil.getSqlSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); List<Student> students = mapper.listStudent(); for (Student student : students) { System.out.println( "学生:" + student.toString() + "\t的老师是:\t" + student.getTeacher().toString() ); } } }
结果
小结
按照查询进行嵌套处理就像SQL中的子查询
按照结果进行嵌套处理就像SQL中的联表查询
一对多
查询一个老师,并且查询这个老师的所有学生
一个老师拥有多个学生
如果对于老师这边,就是一个一对多的现象,即一个老师下面拥有一群学生(集合)!
实体类
import lombok.Data; @Data public class Teacher { private int id; private String name; private List<Student> students;//一个老师多个学生 @Override public String toString() { return "Teacher{" + "id=" + id + ", name='" + name + '\'' + '}'; } } import lombok.Data; @Data public class Student { private int id; private String name; private int tid; }
TeacherMapper接口
public interface TeacherMapper { Teacher getTeacher(int id);//获取指定老师,及老师下的所有学生 Teacher getTeacher2(int id);//获取指定老师,及老师下的所有学生 }
思路:
1. 从学生表和老师表中查出学生id,学生姓名,老师姓名
2. 对查询出来的操作做结果集映射
因为老师类中的学生属性是一个集合,要使用collection
JavaType和ofType都是用来指定对象类型的
JavaType是用来指定pojo中属性的类型
ofType指定的是映射到list集合属性中pojo的类型。
1.第一种,是按照结果进行嵌套处理的
<?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.cong.dao.TeacherMapper"> <resultMap id="teacherMap" type="teacher"> <id property="id" column="id"/> <result property="name" column="tname"/> <collection property="students" ofType="student"> <id property="id" column="sid"/> <result property="name" column="sname"/> <result property="tid" column="tid"/> </collection> </resultMap> <select id="getTeacher" resultMap="teacherMap"> select t.id,t.name tname,s.id sid,s.name sname,s.tid from teacher t,student s where t.id = s.tid and t.id = #{id} </select> </mapper>
2.还有一种,是按照查询进行嵌套处理的
<select id="getTeacher2" resultMap="teacherMap2"> select * from teacher where id = #{id} </select> <select id="getStudentByTeacherId" resultType="student"> select * from student where tid = #{id} </select> <resultMap id="teacherMap2" type="teacher"> <id property="id" column="id"/> <!--column是一对多的外键 , 写的是一对多种一的主键的列名--> <collection property="students" column="id" javaType="arrayList" ofType="student" select="getStudentByTeacherId"/> </resultMap>
测试类
public class MyTest { @Test public void test1() { SqlSession sqlSession = MybatisUtil.getSqlSession(); TeacherMapper teacherMapper = sqlSession.getMapper(TeacherMapper.class); Teacher teacher = teacherMapper.getTeacher(2); System.out.println("老师: " + teacher.toString() + "\n他的学生:"); List<Student> students = teacher.getStudents(); for (Student student : students) { System.out.println("\t"+student.toString()); } sqlSession.close(); } }
结果
小结
- 关联-association
- 集合-collection
- 所以association是用于一对一和多对一,而collection是用于一对多的关系
-
JavaType和ofType都是用来指定对象类型的
- JavaType是用来指定pojo中属性的类型
- ofType指定的是映射到list集合属性中pojo的类型。
注意说明:
- 保证SQL的可读性,尽量通俗易懂
- 根据实际要求,尽量编写性能更高的SQL语句
- 注意属性名和字段不一致的问题
- 注意一对多和多对一 中:字段和属性对应的问题
- 尽量使用Log4j,通过日志来查看自己的错误
爱生活,爱码字
我是匆匆、我曾喂自己半年酒。
好好生活吧,有缘或许相见。