Mybatis学习笔记-复杂查询

  • 多个学生,对应一个老师
  • 对于学生而言,关联:多个学生关联一个老师【多对一】
  • 对于老师而言,集合:一个老师,有多个学生【一对多】

复杂查询环境搭建

数据库搭建

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=utf8INSERT 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);

创建Maven项目

  • pom.xml配置所使用的依赖
    <!--导入依赖-->
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>
        <!--数据库连接-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>
        <!--Junit测试单元-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
  • Mybatis核心配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" >
<!--核心配置文件-->
<configuration>
    <!--引入外部配置文件(db.properties)-->
    <properties resource="db.properties"/>

    <settings>
        <!--标准日志工厂实现-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <!--引入别名(扫描包)-->
    <typeAliases>
        <package name="cn.iris.pojo"/>
    </typeAliases>

    <!--配置环境-->
    <environments default="test">
        <environment id="test">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

</configuration>
  • 创建项目包结构(pojo,dao,utils)
    • pojo
      • Student
      • Teacher
    • Dao
      • StudentMapper
      • TeacherMapper
    • Utils
      • MybatisUtil
package cn.iris.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

// SqlSessionFactory --> SqlSession
public class MybatisUtils {

    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            // 使用Mybatis获取SqlSessionFactory对象
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // 有了 SqlSessionFactory,我们可以从中获得 SqlSession 的实例
    public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession();
    }

}
  • 编写实体类
    • Class Teacher
package cn.iris.pojo;

public class Teacher {

    private int id;
    private String name;

    public Teacher() {}

    public Teacher(int id, String name) {
        this.id = id;
        this.name = name;
    }

    Setter&Getter

    @Override
    public String toString()
}
    • Class Student
package cn.iris.pojo;

public class Student {
    private int id;
    private String name;
    private Teacher teacher;

    public Student(int id, String name, Teacher teacher) {
        this.id = id;
        this.name = name;
        this.teacher = teacher;
    }

    public Student() {
    }

    Setter&Getter

    @Override
    public String toString()
}
  • 编写与实体类绑定的Mapper.xml
    • resource.cn.iris.dao
    • 一定要在核心配置文件中注册Mapper.xml
<!--以TeacherMapper为例-->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="cn.iris.dao.TeacherMapper">

</mapper>

测试环境搭建

  • TeacherMapper中测试getTeacherById()方法
// 使用注解进行简单查询测试
@Select("SELECT * FROM teacher WHERE id = #{id}")
Teacher getTeacherById(@Param("id") int id);

多对一 具体代码实现

  • 查询所有学生以及其对应的老师信息

<!--思路:
    1. 查询所有的学生信息
    2. 根据学生tid 寻找 对应的老师
-->

方法一

  • 查询嵌套【子查询处理】
    <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 集合:collection-->
            <!--property 属性名
                column 字段名
                javaType 对应的Java对象(全类名/别名)
                select 嵌套查询
            -->
        <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
    </resultMap>
    <select id="getTeacher" resultType="Teacher">
        SELECT * FROM teacher WHERE id = #{tid};
    </select>

方法二

  • 按照结果嵌套处理【SQL联表查询】
    <select id="getStudent2" resultMap="StudentTeacher2">
        SELECT s.id sid,s.name sname,t.id tid,t.name 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="name" column="tname"/>
            <result property="id" column="tid"/>
        </association>
    </resultMap>

一对多 具体代码实现

环境搭建

  • Class Teacher
package cn.iris.pojo;

public class Student {
    private int id;
    private String name;
    private int tid;

    public Student() {
    }

    public Student(int id, String name, int tid) {
        this.id = id;
        this.name = name;
        this.tid = tid;
    }

    Setter&Getter

    @Override
    public String toString()
    }
}
  • Class Student
package cn.iris.pojo;

import java.util.List;

public class Teacher {

    private int id;
    private String name;
    private List<Student> students;

    public Teacher(){}

    public Teacher(int id, String name, List<Student> students) {
        this.id = id;
        this.name = name;
        this.students = students;
    }

    Setter&Getter

    @Override
    public String toString()
    }
}
  • 查询指定ID老师及其全部学生

    • 【联表查询】结果集嵌套处理
    <!--按结果嵌套查询-->
    <select id="getTeacherStudents" resultMap="TeacherStudent">
        SELECT s.id sid, s.name sname, t.id tid,t.name tname FROM student s, teacher t
        WHERE s.tid = t.id AND t.id = #{id};
    </select>

    <resultMap id="TeacherStudent" type="Teacher">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
        <collection property="students" ofType="Student">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="tid" column="tid"/>
        </collection>
    </resultMap>
    • 【子查询】查询嵌套
    <!--子查询-->
    <select id="getTeacherStudents2" resultMap="TeacherStudent2">
        SELECT * FROM teacher WHERE id = #{id}
    </select>
    <resultMap id="TeacherStudent2" type="Teacher">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <collection property="students" javaType="ArrayList" ofType="Student" select="getStudent" column="id"/>
    </resultMap>
    <select id="getStudent" resultType="Student">
        SELECT * FROM student WHERE tid = #{tid}
    </select>

总结

  1. 关联 - association【多对一】
  2. 集合 - collection【一对多】
  3. javaType & ofType
    • javaType:用来指定实体类中属性类型
    • ofType:用来指定指定映射到List/集合中的pojo类型(泛型中的约束类型)
  4. 注意点
    • 确保SQL的可读性(通俗易懂)
    • 注意【一对多】和【多对一】中的属性名&字段问题
    • 如果问题不好排错 --> 使用日志,查看log文件
  5. Mybatis执行流程

【面试涉及问题】

posted @ 2021-08-06 17:31  菜鸢爱敲bug  阅读(109)  评论(0编辑  收藏  举报