• MyBatis(三)


    6. 自定义映射resultMap

    6.1 代码结构

    在这里插入图片描述

    SqlSessionUtils.java、jdbc.properties、log4j.xml延用上面章节的。

    6.1.1 mybatis-config.xml

    
    DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    
        <properties resource="jdbc.properties"/>
    
        
        <settings>
            
            <setting name="mapUnderscoreToCamelCase" value="true"/>
            
            <setting name="lazyLoadingEnabled" value="true"/>
        settings>
    
        <typeAliases>
            <package name="com.atguigu.mybatis.pojo"/>
        typeAliases>
    
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driver}"/>
                    <property name="url" value="${jdbc.url}"/>
                    <property name="username" value="${jdbc.username}"/>
                    <property name="password" value="${jdbc.password}"/>
                dataSource>
            environment>
        environments>
    
        <mappers>
            <package name="com.atguigu.mybatis.mapper"/>
        mappers>
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    6.1.2 pojo

    Dept

    部门信息

    package com.atguigu.mybatis.pojo;
    
    public class Dept {
        private Integer did;
    
        private String deptName;
        //省略get、set
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    Emp

    员工信息

    package com.atguigu.mybatis.pojo;
    
    public class Emp {
    
        private Integer eid;
    
        private String empName;
    
        private Integer age;
    
        private String sex;
    
        private String email;
    
        //员工所属部门
        private Dept dept;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    6.1.3 mapper

    EmpMapper
    package com.atguigu.mybatis.mapper;
    
    import com.atguigu.mybatis.pojo.Emp;
    
    public interface EmpMapper {
        /**
         * 查询所有的员工信息
         */
        List<Emp> getAllEmp();
    
        /**
         * 查询员工以及员工所对应的部门信息
         */
        Emp getEmpAndDept(@Param("eid") Integer eid);
    
        /**
         * 通过分步查询查询员工以及员工所对应的部门信息
         * 分步查询第一步:查询员工信息
         */
        Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);
    
        /**
         * 通过分步查询查询部门以及部门中所有的员工信息
         * 分步查询第二步:根据did查询员工信息
         */
        List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    DeptMapper
    package com.atguigu.mybatis.mapper;
    
    import com.atguigu.mybatis.pojo.Dept;
    
    public interface DeptMapper {
    
        /**
         * 通过分步查询查询员工以及员工所对应的部门信息
         * 分步查询第二步:通过did查询员工所对应的部门
         */
        Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);
    
        /**
         * 获取部门以及部门中所有的员工信息
         */
        Dept getDeptAndEmp(@Param("did") Integer did);
    
        /**
         * 通过分步查询查询部门以及部门中所有的员工信息
         * 分步查询第一步:查询部门信息
         */
        Dept getDeptAndEmpByStepOne(@Param("did") Integer did);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    6.2 映射文件和测试编写

    在这里插入图片描述

    EmpMapper.xml

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.atguigu.mybatis.mapper.EmpMapper">
    
        
        <resultMap id="empResultMap" type="Emp">
            <id property="eid" column="eid">id>
            <result property="empName" column="emp_name">result>
            <result property="age" column="age">result>
            <result property="sex" column="sex">result>
            <result property="email" column="email">result>
        resultMap>
    
        
        <select id="getAllEmp" resultMap="empResultMap">
            select * from t_emp
        select>
    
        
        <resultMap id="empAndDeptResultMapOne" type="Emp">
            <id property="eid" column="eid">id>
            <result property="empName" column="emp_name">result>
            <result property="age" column="age">result>
            <result property="sex" column="sex">result>
            <result property="email" column="email">result>
            <result property="dept.did" column="did">result>
            <result property="dept.deptName" column="dept_name">result>
        resultMap>
        
        <resultMap id="empAndDeptResultMapTwo" type="Emp">
            <id property="eid" column="eid">id>
            <result property="empName" column="emp_name">result>
            <result property="age" column="age">result>
            <result property="sex" column="sex">result>
            <result property="email" column="email">result>
            
            <association property="dept" javaType="Dept">
                <id property="did" column="did">id>
                <result property="deptName" column="dept_name">result>
            association>
        resultMap>
        
        <select id="getEmpAndDept" resultMap="empAndDeptResultMapTwo">
            select * from t_emp left join t_dept on t_emp.did = t_dept .did where t_emp.eid = #{eid}
        select>
    
        <resultMap id="empAndDeptByStepResultMap" type="Emp">
            <id property="eid" column="eid">id>
            <result property="empName" column="emp_name">result>
            <result property="age" column="age">result>
            <result property="sex" column="sex">result>
            <result property="email" column="email">result>
            
            <association property="dept"
                         select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
                         column="did"
                         fetchType="eager">association>
        resultMap>
        
        <select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">
            select * from t_emp where eid = #{eid}
        select>
    
        <select id="getAllEmpOld" resultType="Emp">
            
            select * from t_emp
        select>
    
        
        <select id="getDeptAndEmpByStepTwo" resultType="Emp">
            select * from t_emp where did = #{did}
        select>
    
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96

    ResultMapTest.java

    package com.atguigu.mybatis.test;
    
    import com.atguigu.mybatis.mapper.DeptMapper;
    import com.atguigu.mybatis.mapper.EmpMapper;
    import com.atguigu.mybatis.pojo.Dept;
    import com.atguigu.mybatis.pojo.Emp;
    import com.atguigu.mybatis.utils.SqlSessionUtils;
    
    public class ResultMapTest {
    
        /**
         * 解决字段名和属性名不一致的情况:
         * a>为字段起别名,保持和属性名的一致
         * b>设置全局配置,将_自动映射为驼峰
         * 
         * c>通过resultMap设置自定义的映射关系
         * 
         *     
         *     
         *     
         *     
         *     
         * 
         *
         * 处理多对一的映射关系:
         * a>级联属性赋值
         * b>association
         * c>分步查询
         *
         * 处理一对多的映射关系
         * a>collection
         * b>分步查询
         */
    
        @Test
        public void testGetEmpAndDeptByStep(){
            SqlSession sqlSession = SqlSessionUtils.getSqlSession();
            EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
            Emp emp = mapper.getEmpAndDeptByStepOne(3);
            System.out.println(emp.getEmpName());
            System.out.println("+++++++++++++++++++++++++++++++++++++");
            System.out.println(emp.getDept());
        }
    
        @Test
        public void testGetEmpAndDept(){
            SqlSession sqlSession = SqlSessionUtils.getSqlSession();
            EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
            Emp emp = mapper.getEmpAndDept(3);
            System.out.println(emp);
        }
    
        @Test
        public void testGetAllEmp(){
            SqlSession sqlSession = SqlSessionUtils.getSqlSession();
            EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
            List<Emp> list = mapper.getAllEmp();
            list.forEach(emp -> System.out.println(emp));
        }
    
        @Test
        public void testGetDeptAndEmp(){
            SqlSession sqlSession = SqlSessionUtils.getSqlSession();
            DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
            Dept dept = mapper.getDeptAndEmp(1);
            System.out.println(dept);
        }
    
        @Test
        public void testGetDeptAndEmpByStep(){
            SqlSession sqlSession = SqlSessionUtils.getSqlSession();
            DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
            Dept dept = mapper.getDeptAndEmpByStepOne(1);
            System.out.println(dept.getDeptName());
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    6.2.1 resultMap处理字段和属性的映射关系

    resultMap:设置自定义映射
    id:表示自定义映射的唯一标识,不能重复
    type:查询的数据要映射的实体类的类型
    id:设置主键的映射关系
    result:设置普通字段的映射关系
    property:设置映射关系中实体类中的属性名
    column:设置映射关系中中的字段名

    EmpMapper.xml

    若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射,即使字段名和属性名一致的属性也要映射,也就是全部属性都要列出来

    
    <resultMap id="empResultMap" type="Emp">
    	
        <id property="eid" column="eid">id>
    	<result property="empName" column="emp_name">result>
    	<result property="age" column="age">result>
    	<result property="sex" column="sex">result>
    	<result property="email" column="email">result>
    resultMap>
    
    
    <select id="getAllEmp" resultMap="empResultMap">
    	select * from t_emp
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
        @Test
    	//获取所有的员工
        public void testGetAllEmp(){
            SqlSession sqlSession = SqlSessionUtils.getSqlSession();
            EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
            List<Emp> list = mapper.getAllEmp();
            list.forEach(emp -> System.out.println(emp));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    若字段名和实体类中的属性名不一致,但是字段名符合数据库的规则(使用_),实体类中的属性名符合Java的规则(使用驼峰)。此时也可通过以下两种方式处理字段名和实体类中的属性的映射关系

    1. 可以通过为字段起别名的方式,保证和实体类中的属性名保持一致

      
      <select id="getAllEmp" resultType="Emp">
      	select eid,emp_name empName,age,sex,email from t_emp
      select>
      
      • 1
      • 2
      • 3
      • 4
    2. 可以在MyBatis的核心配置文件中的setting标签中,设置一个全局配置信息mapUnderscoreToCamelCase,可以在查询表中数据时,自动将_类型的字段名转换为驼峰,例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为userName。

      <settings>
       <setting name="mapUnderscoreToCamelCase" value="true"/>
      settings>
      
      • 1
      • 2
      • 3

    6.2.2 多对一映射处理

    查询员工信息以及员工所对应的部门信息

    public class Emp {  
    	private Integer eid;  
    	private String empName;  
    	private Integer age;  
    	private String sex;  
    	private String email;  
        
        //加一行这个    员工所属的部门  多个员工对应一个部门
    	private Dept dept;
    	//...构造器、get、set方法等
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    6.2.2.1 级联方式处理映射关系
    <resultMap id="empAndDeptResultMapOne" type="Emp">
    	<id property="eid" column="eid">id>
    	<result property="empName" column="emp_name">result>
    	<result property="age" column="age">result>
    	<result property="sex" column="sex">result>
    	<result property="email" column="email">result>
        
    	<result property="dept.did" column="did">result>
    	<result property="dept.deptName" column="dept_name">result>
    resultMap>
    
    
    <select id="getEmpAndDept" resultMap="empAndDeptResultMapOne">
    	select * from t_emp left join t_dept on t_emp.eid = t_dept.did where t_emp.eid = #{eid}
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
        @Test
    	//获取员工信息  和这个员工所属的部门
        public void testGetEmpAndDept(){
            SqlSession sqlSession = SqlSessionUtils.getSqlSession();
            EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
            Emp emp = mapper.getEmpAndDept(3);
            System.out.println(emp);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    6.2.2.2 使用association处理映射关系
    • association:处理多对一的映射关系
    • property:需要处理多对的映射关系的属性名
    • javaType:该属性的类型
    <resultMap id="empAndDeptResultMapTwo" type="Emp">
    	<id property="eid" column="eid">id>
    	<result property="empName" column="emp_name">result>
    	<result property="age" column="age">result>
    	<result property="sex" column="sex">result>
    	<result property="email" column="email">result>
    	
        <association property="dept" javaType="Dept">
    		<id property="did" column="did">id>
    		<result property="deptName" column="dept_name">result>
    	association>
    resultMap>
    
    
    <select id="getEmpAndDept" resultMap="empAndDeptResultMapTwo">
    	select * from t_emp left join t_dept on t_emp.eid = t_dept.did where t_emp.eid = #{eid}
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    6.2.2.3 分步查询

    1. 查询员工信息

    • select:设置分布查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)
    • column:设置分步查询的条件
    //EmpMapper里的方法
    /**
     * 通过分步查询,员工及所对应的部门信息
     * 分步查询第一步:查询员工信息
     * @param  
     * @return com.atguigu.mybatis.pojo.Emp
     */
    Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    <resultMap id="empAndDeptByStepResultMap" type="Emp">
    	<id property="eid" column="eid">id>
    	<result property="empName" column="emp_name">result>
    	<result property="age" column="age">result>
    	<result property="sex" column="sex">result>
    	<result property="email" column="email">result>
        
        	
        <association property="dept"
    				 select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
    				 column="did">association>
    resultMap>
    
    
    <select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">
    	select * from t_emp where eid = #{eid}
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    2. 查询部门信息

    //DeptMapper里的方法
    /**
     * 通过分步查询,员工及所对应的部门信息
     * 分步查询第二步:通过did查询员工对应的部门信息
     * @param
     * @return com.atguigu.mybatis.pojo.Emp
     */
    Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    
    <resultMap id="EmpAndDeptByStepTwoResultMap" type="Dept">
    	<id property="did" column="did">id>
    	<result property="deptName" column="dept_name">result>
    resultMap>
    
    
    <select id="getEmpAndDeptByStepTwo" resultMap="EmpAndDeptByStepTwoResultMap">
    	select * from t_dept where did = #{did}
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    6.2.3 一对多映射处理

    在这里插入图片描述

    DeptMapper.xml

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.atguigu.mybatis.mapper.DeptMapper">
    
        
        <select id="getEmpAndDeptByStepTwo" resultType="Dept">
            select * from t_dept where did = #{did}
        select>
    
        <resultMap id="deptAndEmpResultMap" type="Dept">
            <id property="did" column="did">id>
            <result property="deptName" column="dept_name">result>
            
            <collection property="emps" ofType="Emp">
                <id property="eid" column="eid">id>
                <result property="empName" column="emp_name">result>
                <result property="age" column="age">result>
                <result property="sex" column="sex">result>
                <result property="email" column="email">result>
            collection>
        resultMap>
        
        <select id="getDeptAndEmp" resultMap="deptAndEmpResultMap">
            select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #{did}
        select>
    
        <resultMap id="deptAndEmpByStepResultMap" type="Dept">
            <id property="did" column="did">id>
            <result property="deptName" column="dept_name">result>
            <collection property="emps"
                        select="com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
                        column="did" fetchType="eager">collection>
        resultMap>
        
        <select id="getDeptAndEmpByStepOne" resultMap="deptAndEmpByStepResultMap">
            select * from t_dept where did = #{did}
        select>
    
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    public class Dept {
        private Integer did;
        private String deptName;
        //添加这个
        private List<Emp> emps;
    	//...构造器、get、set方法等
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    6.2.3.1 collection
    • collection:用来处理一对多的映射关系
    • ofType:表示该属性对饮的集合中存储的数据的类型
    <resultMap id="DeptAndEmpResultMap" type="Dept">
    	<id property="did" column="did">id>
    	<result property="deptName" column="dept_name">result>
        
    	<collection property="emps" ofType="Emp">
    		<id property="eid" column="eid">id>
    		<result property="empName" column="emp_name">result>
    		<result property="age" column="age">result>
    		<result property="sex" column="sex">result>
    		<result property="email" column="email">result>
    	collection>
    resultMap>
    
    
    <select id="getDeptAndEmp" resultMap="DeptAndEmpResultMap">
    	select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #{did}
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    6.2.3.2 分步查询

    1. 查询部门信息

    /**
     * 通过分步查询,查询部门及对应的所有员工信息
     * 分步查询第一步:查询部门信息
     * @param did 
     * @return com.atguigu.mybatis.pojo.Dept
     */
    Dept getDeptAndEmpByStepOne(@Param("did") Integer did);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    <resultMap id="DeptAndEmpByStepOneResultMap" type="Dept">
    	<id property="did" column="did">id>
    	<result property="deptName" column="dept_name">result>
    	<collection property="emps"
    				select="com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
    				column="did">collection>
    resultMap>
    
    <select id="getDeptAndEmpByStepOne" resultMap="DeptAndEmpByStepOneResultMap">
    	select * from t_dept where did = #{did}
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2. 根据部门id查询部门中的所有员工

    /**
     * 通过分步查询,查询部门及对应的所有员工信息
     * 分步查询第二步:根据部门id查询部门中的所有员工
     * @param did
     * @return java.util.List
     */
    List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    
    <select id="getDeptAndEmpByStepTwo" resultType="Emp">
    	select * from t_emp where did = #{did}
    select>
    
    • 1
    • 2
    • 3
    • 4

    6.2.4 延迟加载

    分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息:

    • lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载
    • aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个属性会按需加载
    • 此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType=“lazy(延迟加载)|eager(立即加载)”
    <settings>
    	
    	<setting name="lazyLoadingEnabled" value="true"/>
    settings>
    
    • 1
    • 2
    • 3
    • 4
    @Test
    public void getEmpAndDeptByStepOne() {
    	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    	EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
    	Emp emp = mapper.getEmpAndDeptByStepOne(1);
    	System.out.println(emp.getEmpName());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    关闭延迟加载,两条SQL语句都运行了
    在这里插入图片描述

    开启延迟加载,只运行获取emp的SQL语句
    在这里插入图片描述

    @Test
    public void getEmpAndDeptByStepOne() {
    	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    	EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
    	Emp emp = mapper.getEmpAndDeptByStepOne(1);
    	System.out.println(emp.getEmpName());
    	System.out.println("----------------");
    	System.out.println(emp.getDept());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    开启后,需要用到查询dept的时候才会调用相应的SQL语句在这里插入图片描述

    fetchType:当开启了全局的延迟加载之后,可以通过该属性手动控制延迟加载的效果,fetchType=“lazy(延迟加载)|eager(立即加载)”

    <resultMap id="empAndDeptByStepResultMap" type="Emp">
    	<id property="eid" column="eid">id>
    	<result property="empName" column="emp_name">result>
    	<result property="age" column="age">result>
    	<result property="sex" column="sex">result>
    	<result property="email" column="email">result>
    	
        <association property="dept"
    				 select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
    				 column="did"
    				 fetchType="lazy">association>
    resultMap>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    7. 动态SQL

    在这里插入图片描述

    Mybatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决拼接SQL语句字符串时的痛点问题

    7.1 if

    • if标签可通过test属性(即传递过来的数据)的表达式进行判断,若表达式的结果为true,则标签中的内容会执行;反之标签中的内容不会执行
    • 在where后面添加一个恒成立条件1=1
    • 这个恒成立条件并不会影响查询的结果
      • 这个1=1可以用来拼接and语句,例如:当empName为null时
      • 如果不加上恒成立条件,则SQL语句为select * from t_emp where and age = ? and sex = ? and email = ?,此时where会与and连用,SQL语句会报错
        • 如果加上一个恒成立条件,则SQL语句为select * from t_emp where 1= 1 and age = ? and sex = ? and email = ?,此时不报错
    
    <select id="getEmpByCondition" resultType="Emp">
    	select * from t_emp where 1=1
    	<if test="empName != null and empName !=''">
    		and emp_name = #{empName}
    	if>
    	<if test="age != null and age !=''">
    		and age = #{age}
    	if>
    	<if test="sex != null and sex !=''">
    		and sex = #{sex}
    	if>
    	<if test="email != null and email !=''">
    		and email = #{email}
    	if>
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
        @Test
        public void testGetEmpByCondition(){
            SqlSession sqlSession = SqlSessionUtils.getSqlSession();
            DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
            List<Emp> list = mapper.getEmpByCondition(new Emp(null, "", null, "", null));
            System.out.println(list);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    7.2 where

    where和if一般结合使用:

    • 若where标签中的if条件都不满足,则where标签没有任何功能,即不会添加where关键字 ;
    • 若where标签中的if条件满足,则where标签会自动添加where关键字,并将条件最前方多余的and/or去掉 。
    
    <select id="getEmpByCondition" resultType="Emp">
    	select * from t_emp
    	<where>
    		<if test="empName != null and empName !=''">
    			emp_name = #{empName}
    		if>
    		<if test="age != null and age !=''">
    			and age = #{age}
    		if>
    		<if test="sex != null and sex !=''">
    			and sex = #{sex}
    		if>
    		<if test="email != null and email !=''">
    			and email = #{email}
    		if>
    	where>
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    注意:where标签不能去掉条件后多余的and/or

    
    <if test="empName != null and empName !=''">
    emp_name = #{empName} and
    if>
    <if test="age != null and age !=''">
    	age = #{age}
    if>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    7.3 trim

    trim用于去掉或添加标签中的内容

    常用属性:

    • prefix:在trim标签中的内容的前面添加某些内容
    • suffix:在trim标签中的内容的后面添加某些内容
    • prefixOverrides:在trim标签中的内容的前面去掉某些内容
    • suffixOverrides:在trim标签中的内容的后面去掉某些内容

    若trim中的标签都不满足条件,则trim标签没有任何效果,也就是只剩下select * from t_emp

    
    <select id="getEmpByCondition" resultType="Emp">
    	select * from t_emp
    	<trim prefix="where" suffixOverrides="and|or">
    		<if test="empName != null and empName !=''">
    			emp_name = #{empName} and
    		if>
    		<if test="age != null and age !=''">
    			age = #{age} and
    		if>
    		<if test="sex != null and sex !=''">
    			sex = #{sex} or
    		if>
    		<if test="email != null and email !=''">
    			email = #{email}
    		if>
    	trim>
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    //测试类
    @Test
    public void getEmpByCondition() {
    	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    	DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
    	List<Emp> emps= mapper.getEmpByCondition(new Emp(null, "张三", null, null, null, null));
    	System.out.println(emps);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    7.4 choose、when、otherwise

    • choose、when、otherwise相当于if...else if..else
    • when至少要有一个,otherwise至多只有一个
    <select id="getEmpByChoose" resultType="Emp">
    	select * from t_emp
    	<where>
    		<choose>
    			<when test="empName != null and empName != ''">
    				emp_name = #{empName}
    			when>
    			<when test="age != null and age != ''">
    				age = #{age}
    			when>
    			<when test="sex != null and sex != ''">
    				sex = #{sex}
    			when>
    			<when test="email != null and email != ''">
    				email = #{email}
    			when>
    			<otherwise>
    				did = 1
    			otherwise>
    		choose>
    	where>
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    @Test
    public void getEmpByChoose() {
    	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    	DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
    	List<Emp> emps = mapper.getEmpByChoose(new Emp(null, "张三", 23, "男", "123@qq.com", null));
    	System.out.println(emps);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    • 相当于if a else if b else if c else d,只会执行其中一个

    7.5 foreach

    • collection:设置要循环的数组或集合
    • item:表示集合或数组中的每一个数据
    • separator:设置循环体之间的分隔符,分隔符前后默认有一个空格,如,
    • open:设置foreach标签中的内容的开始符
    • close:设置foreach标签中的内容的结束符

    批量删除

    
    <delete id="deleteMoreByArray">
    	delete from t_emp where eid in
    	<foreach collection="eids" item="eid" separator="," open="(" close=")">
    		#{eid}
    	foreach>
    delete>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    @Test
    public void deleteMoreByArray() {
    	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    	DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
    	int result = mapper.deleteMoreByArray(new Integer[]{6, 7, 8, 9});
    	System.out.println(result);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    批量添加

    
    <insert id="insertMoreByList">
    	insert into t_emp values
    	<foreach collection="emps" item="emp" separator=",">
    		(null,#{emp.empName},#{emp.age},#{emp.sex},#{emp.email},null)
    	foreach>
    insert>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    @Test
    public void insertMoreByList() {
    	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    	DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
    	Emp emp1 = new Emp(null,"a",1,"男","123@321.com",null);
    	Emp emp2 = new Emp(null,"b",1,"男","123@321.com",null);
    	Emp emp3 = new Emp(null,"c",1,"男","123@321.com",null);
    	List<Emp> emps = Arrays.asList(emp1, emp2, emp3);
    	int result = mapper.insertMoreByList(emps);
    	System.out.println(result);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    7.6 SQL片段

    sql片段,可以记录一段公共sql片段,在使用的地方通过include标签进行引入

    声明sql片段:标签

    <sql id="empColumns">eid,emp_name,age,sex,emailsql>
    
    • 1

    引用sql片段:标签

    
    <select id="getEmpByCondition" resultType="Emp">
    	select <include refid="empColumns">include> from t_emp
    select>
    
    • 1
    • 2
    • 3
    • 4

    8. MyBatis的缓存

    在这里插入图片描述

    8.1 MyBatis的一级缓存

    一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问

    使一级缓存失效的四种情况:

    1. 不同的SqlSession对应不同的一级缓存
    2. 同一个SqlSession但是查询条件不同
    3. 同一个SqlSession两次查询期间执行了任何一次增删改操作
    4. 同一个SqlSession两次查询期间手动清空了缓存

    8.2 MyBatis的二级缓存

    二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取

    二级缓存开启的条件

    1. 在核心配置文件中,设置全局配置属性cacheEnabled=“true”,默认为true,不需要设置
    2. 在映射文件中设置标签
    3. 二级缓存必须在SqlSession关闭或提交之后有效
    4. 查询的数据所转换的实体类类型必须实现序列化的接口

    使二级缓存失效的情况:两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效

    8.2.1 二级缓存的相关配置

    • 在mapper配置文件中添加的cache标签可以设置一些属性
    • eviction属性:缓存回收策略
    • LRU(Least Recently Used) – 最近最少使用的:移除最长时间不被使用的对象。
      • FIFO(First in First out) – 先进先出:按对象进入缓存的顺序来移除它们。
      • SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
      • WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
      • 默认的是 LRU
    • flushInterval属性:刷新间隔,单位毫秒
    • 默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句(增删改)时刷新
    • size属性:引用数目,正整数
    • 代表缓存最多可以存储多少个对象,太大容易导致内存溢出
    • readOnly属性:只读,true/false
    • true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。
      • false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false

    8.3 MyBatis缓存查询的顺序

    • 先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用
    • 如果二级缓存没有命中,再查询一级缓存
    • 如果一级缓存也没有命中,则查询数据库
    • SqlSession关闭之后,一级缓存中的数据会写入二级缓存

    8.4 整合第三方缓存EHCache(了解)

    8.4.1 添加依赖

    pom.xml中添加

    
    <dependency>
    	<groupId>org.mybatis.cachesgroupId>
    	<artifactId>mybatis-ehcacheartifactId>
    	<version>1.2.1version>
    dependency>
    
    <dependency>
    	<groupId>ch.qos.logbackgroupId>
    	<artifactId>logback-classicartifactId>
    	<version>1.2.3version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    8.4.2 各个jar包的功能

    jar包名称作用
    mybatis-ehcacheMybatis和EHCache的整合包
    ehcacheEHCache核心包
    slf4j-apiSLF4J日志门面包
    logback-classic支持SLF4J门面接口的一个具体实现

    8.4.3 创建EHCache的配置文件ehcache.xml

    在这里插入图片描述

    名字必须叫ehcache.xml

    
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
        
        <diskStore path="D:\atguigu\ehcache"/>
        <defaultCache
                maxElementsInMemory="1000"
                maxElementsOnDisk="10000000"
                eternal="false"
                overflowToDisk="true"
                timeToIdleSeconds="120"
                timeToLiveSeconds="120"
                diskExpiryThreadIntervalSeconds="120"
                memoryStoreEvictionPolicy="LRU">
        defaultCache>
    ehcache>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    8.4.4 设置二级缓存的类型

    • 在xxxMapper.xml文件中设置二级缓存类型
    <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
    
    • 1

    8.4.5 加入logback日志

    在这里插入图片描述

    存在SLF4J时,作为简易日志的log4j将失效,此时我们需要借助SLF4J的具体实现logback来打印日志。创建logback的配置文件logback.xml,名字固定,不可改变

    
    <configuration debug="true">
        
        <appender name="STDOUT"
                  class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                
                
                <pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%npattern>
            encoder>
        appender>
        
        
        <root level="DEBUG">
            
            <appender-ref ref="STDOUT" />
        root>
        
        <logger name="com.atguigu.crowd.mapper" level="DEBUG"/>
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    8.4.6 EHCache配置文件说明

    属性名是否必须作用
    maxElementsInMemory在内存中缓存的element的最大数目
    maxElementsOnDisk在磁盘上缓存的element的最大数目,若是0表示无穷大
    eternal设定缓存的elements是否永远不过期。 如果为true,则缓存的数据始终有效, 如果为false那么还要根据timeToIdleSeconds、timeToLiveSeconds判断
    overflowToDisk设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
    timeToIdleSeconds当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时, 这些数据便会删除,默认值是0,也就是可闲置时间无穷大
    timeToLiveSeconds缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
    diskSpoolBufferSizeMBDiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区
    diskPersistent在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false
    diskExpiryThreadIntervalSeconds磁盘缓存的清理线程运行间隔,默认是120秒。每个120s, 相应的线程会进行一次EhCache中数据的清理工作
    memoryStoreEvictionPolicy当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。 默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出

    8.5 映射文件和测试编写

    CacheMapper.java

    package com.atguigu.mybatis.mapper;
    
    import com.atguigu.mybatis.pojo.Emp;
    import org.apache.ibatis.annotations.Param;
    
    public interface CacheMapper {
    
        Emp getEmpByEid(@Param("eid") Integer eid);
    
        void insertEmp(Emp emp);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    CacheMapper.xml

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.atguigu.mybatis.mapper.CacheMapper">
    
        <cache type="org.mybatis.caches.ehcache.EhcacheCache" />
    
        
        <select id="getEmpByEid" resultType="Emp">
            select * from t_emp where eid = #{eid}
        select>
    
        
        <insert id="insertEmp">
            insert into t_emp values(null,#{empName},#{age},#{sex},#{email},null)
        insert>
    
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    CacheMapperTest.java

    package com.atguigu.mybatis.test;
    
    import com.atguigu.mybatis.mapper.CacheMapper;
    import com.atguigu.mybatis.pojo.Emp;
    import com.atguigu.mybatis.utils.SqlSessionUtils;
    
    public class CacheMapperTest {
    
        @Test
        public void testOneCache(){
            SqlSession sqlSession1 = SqlSessionUtils.getSqlSession();
            CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
            Emp emp1 = mapper1.getEmpByEid(1);
            System.out.println(emp1);
            //mapper1.insertEmp(new Emp(null,"abc",23,"男","123@qq.com"));
            sqlSession1.clearCache();
            Emp emp2 = mapper1.getEmpByEid(1);
            System.out.println(emp2);
            /*SqlSession sqlSession2 = SqlSessionUtils.getSqlSession();
            CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);
            Emp emp2 = mapper2.getEmpByEid(1);
            System.out.println(emp2);*/
        }
    
        @Test
        public void testTwoCache(){
            try {
                InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
                SqlSession sqlSession1 = sqlSessionFactory.openSession(true);
                CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
                System.out.println(mapper1.getEmpByEid(1));
                sqlSession1.close();
                SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
                CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);
                System.out.println(mapper2.getEmpByEid(1));
                sqlSession2.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
  • 相关阅读:
    Python数据结构(顺序表)
    代码随想录算法训练营第13天|● 239. 滑动窗口最大值 ● 347.前 K 个高频元素 ● 总结
    丑单2023秋招笔试第二题 我好想逃却到不掉.jpg (C++ DFS)
    java Spring Boot日志输出格式配置方法
    图论|841钥匙和房间
    JavaEE初阶:多线程(初阶)
    Mybatis动态sql条件查询、判断空值和空字符串
    Typora+Node.js+PicGo搭建图床
    Jmeter进阶-接口自动化
    循环结构在反汇编中特征
  • 原文地址:https://blog.csdn.net/qq_39236499/article/details/134326476