• MyBatis学习存档(5)——联表查询


    之前的数据库操作都是基于一张表进行操作的,若一次查询涉及到多张表,那该如何进行操作呢?

    首先明确联表查询的几个关系,大体可以分为一对一和一对多这两种情况,接下来对这两种情况进行分析:

    一、建立表、添加数据、反向生成

    建立teacher、classes、student三张表,并添加几条数据用于后续操作

    进行反向生成

    二、一对一联表查询

    一个班级(classes)只有一个班主任(teacher),即一对一的关系

    仅仅通过反向生成的文件是无法进行联表查询的,因此需要进行一些改动

    package com.pojo;
    
    public class Teacher {
        private Integer id;
        private String name;
    
        public Integer getId() {
            return id;
        }
        public void setId(Integer id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name == null ? null : name.trim();
        }
        
        @Override
        public String toString() {
            return "Teacher [id=" + id + ", name=" + name + "]";
        }
    }
    Teacher类

    在Classes类中添加一个teacher的属性,删除多余的teacher_id:

    package com.pojo;
    
    public class Classes {
        private Integer classId;
        private String className;
        private Teacher teacher;    //一对一对应的teacher
    
        public Integer getClassId() {
            return classId;
        }
        public void setClassId(Integer classId) {
            this.classId = classId;
        }
        public String getClassName() {
            return className;
        }
        public void setClassName(String className) {
            this.className = className;
        }
        public Teacher getTeacher() {
            return teacher;
        }
        public void setTeacher(Teacher teacher) {
            this.teacher = teacher;
        }
        
        @Override
        public String toString() {
            return "Classes [classId=" + classId + ", className=" + className
                    + ", teacher=" + teacher + "]";
        }
    }
    Classes类

    修改接口及mapper映射文件:此处有2种方法进行查询

    在resultMap节点下添加一个association节点,其配置与resultMap类似,该节点可以用于处理“一对一“的类型关系

    package com.mapper;
    
    import com.pojo.Teacher;
    
    public interface TeacherMapper {
        
        Teacher selectTeacherById(Integer id);
        
    }
    TeacherMapper.java
    <?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="com.mapper.TeacherMapper" >
      <resultMap id="BaseResultMap" type="com.pojo.Teacher" >
        <id column="id" property="id" jdbcType="INTEGER" />
        <result column="name" property="name" jdbcType="VARCHAR" />
      </resultMap>
      <sql id="Base_Column_List" >
        id, name
      </sql>
      <select id="selectTeacherById" parameterType="java.lang.Integer" resultMap="BaseResultMap">
          select
          <include refid="Base_Column_List"/>
          from teacher where id=#{id}
      </select>
    </mapper>
    TeacherMapper.xml
    package com.mapper;
    
    import com.pojo.Classes;
    
    public interface ClassesMapper {
        //方法一
        Classes selectByClassId1(Integer classId);
        //方法二
        Classes selectByClassId2(Integer classId);
        
    }
    ClassesMapper.java
    <?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="com.mapper.ClassesMapper" >
    
      <sql id="Base_Column_List">
          class_id,class_name,teacher_id
      </sql>
      <sql id="classesAndTeacher">
          classes.class_id,classes.class_name,teacher.id,teacher.name
      </sql>
      <!-- 
          方法一:直接嵌套查询
      -->
      <resultMap id="ClassesMap1" type="com.pojo.Classes" >
        <id column="class_id" property="classId" jdbcType="INTEGER" />
        <result column="class_name" property="className" jdbcType="VARCHAR" />
        <association property="teacher" javaType="com.pojo.Teacher">
            <id column="id" property="id" jdbcType="INTEGER"/>
            <result column="name" property="name" jdbcType="VARCHAR"/>
        </association>
      </resultMap>
      <select id="selectByClassId1" resultMap="ClassesMap1" parameterType="java.lang.Integer" >
        select
        <include refid="classesAndTeacher"/>
        from classes LEFT JOIN teacher ON classes.teacher_id=teacher.id where classes.class_id=#{classId}
      </select>
      
      <!-- 
          方法二:进行2次查询(可使用懒加载)
      -->
      <resultMap id="ClassesMap2" type="com.pojo.Classes" >
        <id column="class_id" property="classId" jdbcType="INTEGER" />
        <result column="class_name" property="className" jdbcType="VARCHAR" />
        <association property="teacher" javaType="com.pojo.Teacher" column="teacher_id" select="com.mapper.TeacherMapper.selectTeacherById"/>
        <!-- 
            若需设置懒加载,需在mybatis-config.xml中添加下列节点(开启懒加载,关闭急加载)
            <settings>
                开启懒加载
                <setting name="lazyLoadingEnabled" value="true"/>
                关闭急加载
                  <setting name="aggressiveLazyLoading" value="false"/>
              </settings>
            并在association节点中添加fetchType属性并设置为lazy,如下 
        -->
        <!-- <association property="teacher" javaType="com.pojo.Teacher" column="teacher_id" select="com.mapper.TeacherMapper.selectTeacherById" fetchType="lazy"/> -->
      </resultMap>
      <select id="selectByClassId2" resultMap="ClassesMap2" parameterType="java.lang.Integer">
          select
          <include refid="Base_Column_List"/>
          from classes where class_id=#{id}
      </select>
    </mapper>
    ClassesMapper.xml

    编写测试类

    package com.test;
    
    import java.io.InputStream;
    
    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 com.mapper.ClassesMapper;
    import com.pojo.Classes;
    
    public class TestHasOne {
        
        public static void main(String[] args) throws Exception {
            //mybatis的核心配置文件
            String resource = "mybatis-config.xml";
            //使用MyBatis提供的Resources类加载mybatis的配置文件
            InputStream  is = Resources.getResourceAsStream(resource);
            //构建SqlSession的工厂
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
            //开启SqlSession
            SqlSession session = factory.openSession();
            //通过映射接口执行操作
            ClassesMapper mapper = session.getMapper(ClassesMapper.class);
            Classes clazz1 = mapper.selectByClassId1(1);
            System.out.println("方法一:" + clazz1);
            Classes clazz2 = mapper.selectByClassId2(1);
            System.out.println("方法二:" + clazz2);
            session.close();
        }
    
    }
    TestHasOne

    输出结果如下:

    可从日志输出中看出,方法一仅执行了1条查询语句,方法二执行了2条查询语句

    三、一对多联表查询

    一个班级(classes)中有许多学生(student),即一对多的关系

    修改反向生成的文件

    删除Student类中多余的cId属性

    package com.pojo;
    
    public class Student {
        private Integer id;
        private String name;
    
        public Integer getId() {
            return id;
        }
        public void setId(Integer id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name == null ? null : name.trim();
        }
        
        @Override
        public String toString() {
            return "Student [id=" + id + ", name=" + name + "]";
        }
    }
    Student

    在Classes类中添加一个List<Student>类型的students集合

    package com.pojo;
    
    import java.util.List;
    
    public class Classes {
        private Integer classId;
        private String className;
        private Teacher teacher;    //一对一对应的teacher
        private List<Student> students;    //一对多对应的students
    
        public Integer getClassId() {
            return classId;
        }
        public void setClassId(Integer classId) {
            this.classId = classId;
        }
        public String getClassName() {
            return className;
        }
        public void setClassName(String className) {
            this.className = className;
        }
        public Teacher getTeacher() {
            return teacher;
        }
        public void setTeacher(Teacher teacher) {
            this.teacher = teacher;
        }
        public List<Student> getStudents() {
            return students;
        }
        public void setStudents(List<Student> students) {
            this.students = students;
        }
        
        @Override
        public String toString() {
            return "Classes [classId=" + classId + ", className=" + className
                    + ", teacher=" + teacher + ", students=" + students + "]";
        }
    }
    Classes

    修改接口及mapper映射文件:

    在resultMap节点下添加一个association节点,其配置与resultMap类似,该节点可以用于处理“一对多“的类型关系

    package com.mapper;
    
    import com.pojo.Student;
    
    public interface StudentMapper {
        
        Student selectStudentById(Integer cId);
        
    }
    StudentMapper.java
    <?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="com.mapper.StudentMapper" >
      <resultMap id="BaseResultMap" type="com.pojo.Student" >
        <id column="id" property="id" jdbcType="INTEGER" />
        <result column="name" property="name" jdbcType="VARCHAR" />
      </resultMap>
      <sql id="Base_Column_List" >
        id, name
      </sql>
      <select id="selectStudentById" resultMap="BaseResultMap" parameterType="java.lang.Integer">
          select
          <include refid="Base_Column_List"/>
          from student where c_id=#{cId}
      </select>
    </mapper>
    StudentMapper.xml
    package com.mapper;
    
    import com.pojo.Classes;
    
    public interface ClassesMapper {
        //方法一
        Classes selectByClassId1(Integer classId);
        //方法二
        Classes selectByClassId2(Integer classId);
        //一对多查询
        Classes selectByClassId3(Integer classId);
    }
    ClassesMapper.java
    <?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="com.mapper.ClassesMapper" >
    
      <sql id="Base_Column_List">
          class_id,class_name,teacher_id
      </sql>
      <sql id="classesAndTeacher">
          classes.class_id,classes.class_name,teacher.id,teacher.name
      </sql>
      <sql id="classesAndStudent">
          classes.class_id,classes.class_name,student.id,student.name
      </sql>
      <!-- 
          方法一:直接嵌套查询
      -->
      <resultMap id="ClassesMap1" type="com.pojo.Classes" >
        <id column="class_id" property="classId" jdbcType="INTEGER" />
        <result column="class_name" property="className" jdbcType="VARCHAR" />
        <association property="teacher" javaType="com.pojo.Teacher">
            <id column="id" property="id" jdbcType="INTEGER"/>
            <result column="name" property="name" jdbcType="VARCHAR"/>
        </association>
      </resultMap>
      <select id="selectByClassId1" resultMap="ClassesMap1" parameterType="java.lang.Integer" >
        select
        <include refid="classesAndTeacher"/>
        from classes LEFT JOIN teacher ON classes.teacher_id=teacher.id where classes.class_id=#{classId}
      </select>
      
      <!-- 
          方法二:进行2次查询(可使用懒加载)
      -->
      <resultMap id="ClassesMap2" type="com.pojo.Classes" >
        <id column="class_id" property="classId" jdbcType="INTEGER" />
        <result column="class_name" property="className" jdbcType="VARCHAR" />
        <association property="teacher" javaType="com.pojo.Teacher" column="teacher_id" select="com.mapper.TeacherMapper.selectTeacherById"/>
        <!-- 
            若需设置懒加载,需在mybatis-config.xml中添加下列节点(开启懒加载,关闭急加载)
            <settings>
                开启懒加载
                <setting name="lazyLoadingEnabled" value="true"/>
                关闭急加载
                  <setting name="aggressiveLazyLoading" value="false"/>
              </settings>
            并在association节点中添加fetchType属性并设置为lazy,如下 
        -->
        <!-- <association property="teacher" javaType="com.pojo.Teacher" column="teacher_id" select="com.mapper.TeacherMapper.selectTeacherById" fetchType="lazy"/> -->
      </resultMap>
      <select id="selectByClassId2" resultMap="ClassesMap2" parameterType="java.lang.Integer">
          select
          <include refid="Base_Column_List"/>
          from classes where class_id=#{id}
      </select>
      
      <!-- 一对多查询 -->
      <resultMap id="ClassesMap3" type="com.pojo.Classes" >
        <id column="class_id" property="classId" jdbcType="INTEGER" />
        <result column="class_name" property="className" jdbcType="VARCHAR" />
        <association property="teacher" javaType="com.pojo.Teacher" column="teacher_id" select="com.mapper.TeacherMapper.selectTeacherById"/>
        <collection property="students" column="class_id" ofType="com.pojo.Student" select="com.mapper.StudentMapper.selectStudentById"/>
      </resultMap>
      <select id="selectByClassId3" resultMap="ClassesMap3" parameterType="java.lang.Integer">
          select
          <include refid="Base_Column_List"/>
          from classes where class_id=#{id}
      </select>
    </mapper>
    ClassesMapper.xml

    编写测试类

    package com.test;
    
    import java.io.InputStream;
    
    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 com.mapper.ClassesMapper;
    import com.pojo.Classes;
    
    public class TestHasMany {
        
        public static void main(String[] args) throws Exception{
            //mybatis的核心配置文件
            String resource = "mybatis-config.xml";
            //使用MyBatis提供的Resources类加载mybatis的配置文件
            InputStream  is = Resources.getResourceAsStream(resource);
            //构建SqlSession的工厂
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
            //开启SqlSession
            SqlSession session = factory.openSession();
            //通过映射接口执行操作
            ClassesMapper mapper = session.getMapper(ClassesMapper.class);
            Classes clazz = mapper.selectByClassId3(1);
            System.out.println(clazz);
        }
    
    }
    TestHasMany

    输出结果如下

    Classes [classId=1, className=一年1班, teacher=Teacher [id=2, name=教师B], students=[Student [id=1, name=张三], Student [id=2, name=李四], Student [id=3, name=王五]]]

  • 相关阅读:
    linux中fork()函数详解
    并发和并行有什么区别?
    利用bochs调试Linux 0.11内核
    [调整] Firemonkey iOS 原生 Edit 透明框, 改变框色
    [修正] Firemonkey Windows 控件有虚线残影问题
    [示例] Firemonkey 图片按钮(3态)
    [示例] Firemonkey 不规则按钮实做
    [函数] Delphi FMX Windows 取得下载 Downloads 目录
    [工具] Firemonkey Style 调色工具(可另存 Style 文件)
    [教学] Delphi Berlin 10.1 开发 Windows 10 平板 App 远程调试
  • 原文地址:https://www.cnblogs.com/s1165482267/p/8078862.html
Copyright © 2020-2023  润新知