zoukankan      html  css  js  c++  java
  • MyBatis 映射文件详解

    1. MyBatis 映射文件之<select>标签

    1. <select>用来定义查询操作;
      • "id": 唯一标识符,需要和接口中的方法名一致;
      • parameterType: 参数类型,可以不传,MyBatis 会根据 TypeHandler 自动推断;
      • resultType: 返回值类型;使用别名或全类名,如果返回的是集合,定义集合中元素的类型;
        不能和 resultMap 同时使用;
      • resultMap:可以实现高级结果集映射;
    // Department.java
    public class Department{
        private Integer id;
        private String departmentName;
        private List<Employee> emps;
    
        get 和 set 方法(略)
    }
    
    // Employee.java
    public class Employee{
        private Integer id;
        private String lastName;
        private String email;
        private String gender;
        private Department dept;
    
        get 和 set 方法(略)
    }
    
    // EmployeeMapper.java 接口
    public interface EmployeeMapper(){
    
        // 查询单个
        public Employee getEmpById(Integer id);
    
        // 返回 List 集合
        public List<Employee> getEmpsByLastNameLike(String lastName);
    
        // 返回一条记录,类型为map: key 就是列名,值就是对应的值
        public Map<String,Object> getEmpByIdReturnMap(Integer id);
    
        // 返回多条记录,封装到一个map中: Map<Integer,Employee>: 键为该条记录的主键,
        // 值是封装后的 JavaBean 对象
        // @MapKey 用于指定map集合的主键
        @MapKey("id")
        public Map<Integer,Employee> getEmpByLastNameLikeReturnMap(String lastName);
    
        // 查询员工和所在部门信息
        public Employee getEmpAndDept(Integer id);
    
        // 查询员工和所在部门信息(分步查询)
        public Employee getEmpByIdStep(Integer id);
    
        // 查询某个部门下的具体员工信息
        public List<Employee> getEmpsByDeptId(Integer deptId);
    }
    
    // EmployeeMapper.xml
    <!--
        resultMap: 自定义结果集映射规则;
        type: 自定义规则的 Java 类型
        id: 唯一标识,方便引用
    -->
    <resultMap type="cn.itcast.mybatis.bean.Employee" id="MyEmp">
    
    <!--
        id: 指定主键列的封装规则;
        column: 指定哪一列; prperty: 指定对应的 JavaBean 属性;
        result: 定义普通列封装规则
        其他不指定的列会自动封装; 建议: 只要写resultMap,就把全列的映射都写上
    -->
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
    </resultMap>
    
    <select id="getEmpById" resultMap="MyEmp">
        select * from tbl_employee where id=#{id}
    </select>
    
    <select id="getEmpsByLastNameLike" resultType="cn.itcast.mybatis.bean.Employee">
        select * from tbl_employee where last_name like #{lastName}
    </select>
    
    <select id="getEmpByIdReturnMap" resultType="map">
        select * from tbl_employee where id=#{id}
    </select>
    
    <select id="getEmpByLastNameLikeReturnMap" resultType="cn.itcast.mybatis.bean.Employee">
        select * from tbl_employee where last_name like #{lastName}
    </select>
    
    <!-- 查询某个部门下的具体员工信息 -->
    <select id="getEmpsByDeptId" resultType="cn.itcast.mybatis.bean.Employee">
        select * from tbl_employee where d_id=#{deptId}
    </select>
    
    <!--
        resultMap 使用场景一: 查询员工的同时查询员工对应的部门
    -->
    <resultMap type="cn.itcast.mybatis.bean.Employee" id="MyDifEmp">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="gender" property="gender"/>
    
        <!-- 第一种方式: 联合查询,使用级联属性封装结果集 -->
        <result column="did" property="dept.id"/>
        <result column="dept_name" property="dept.departmentName"/>
    
        <!-- 第二种方式: 使用 association 标签,可以指定联合的javaBean对象
            property="dept": 指定哪个属性是联合的对象;
            javaType: 指定这个属性对象的类型(不能省略)
         -->
         <association property="dept" javaType="cn.itcast.mybatis.bean.Department">
            <id column="did" property="id"/>
            <result column="dept_name" property="departmentName"/>
         </association>
    </resultMap>
    <select id="getEmpAndDept" resultMap="MyDifEmp">
        SELECT e.id id,e.last_name last_name,e.gender gender,e.d_id d_id,
               d.id did,d.dept_name dept_name
        FROM tbl_employee e,tbl_dept d
        WHERE e.d_id=d.id AND e.id=#{id};
    </select>
    
    <!-- 第三种方式: 使用 associatioin 进行分步查询
              1. 新建 DepartmentMapper 接口, getDeptById(Integer id) 方法
              2. 创建对应的映射文件,并在 web.xml 中进行注册
              3. 查询员工的同时查询员工对应的部门(分布查询)
                   3.1 先按照员工 id 查询员工信息;
                   3.2 根据查询到的员工信息中的 d_id 值去部门表查出部门信息;
                   3.3 将部门设置到员工中;
    -->
    <resultMap type="cn.itcast.mybatis.bean.Employee" id="MyEmpByStep">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="email" property="email"/>
        <result column="gender" property="gender"/>
    
        <!-- association 定义关联对象的封装规则
             select: 表名当前属性是调用 select 指定的方法查出的结果
             column: 指定将哪一列的值传给这个查询方法
    
          流程: 使用select 指定的方法(传入column指定的这列参数的值)查出对象,并封装给 property 指定的属性
        -->
        <association property="dept"
                     select="cn.itcast.mybatis.dao.DepartmentMapper.getDeptById"
                     column="d_id">
        </association>
    </resultMap>
    <select id="getEmpByIdStep" resultMap="MyEmpByStep">
        select * from tbl_employee where id=#{id}
    </select>
    
    <!-- 分步查询可以实现延迟加载:
                我们每次查询 Employee 对象的时候,都将Employee 和 Department 一起查询出来;
                改进: 部门信息在我们使用的时候,再去查询
                分步查询的基础之上,在 mybatis-config.xml 中添加两个配置
                <settings>
                    <setting name="lazyLoadingEnabled" value="true"/>
                    <setting name="aggressiveLazyLoading" value="false"/>
                </settings>
    -->
    
    <!--
        resultMap 中的标签:
                  鉴别器: <discriminator javaType=""></discriminator>
                        mybatis 可以使用 discriminator 判断某列的值,然后根据某列的值改变封装行为
        以封装 Employee 为例:
            如果查询出的是女生,就把部门信息查询出来,否则,不查询;
            如果是男生: 把 last_name 这一列的值赋值给 email;
    -->
    
    <resultMap type="cn.itcast.mybatis.bean.Employee" id="MyEmpDis">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="email" property="email"/>
        <result column="gender" property="gender"/>
    
        <!-- column: 指定要判断的列
             javaType: 列值对应的 java 类型; mybatis 已经为 java 类型起了别名
        -->
        <discriminator javaType="string" column="gender">
            <!-- 0 表示女生, resultType: 指定封装的结果类型,不能缺少 -->
            <case value="0" resultType="cn.itcast.mybatis.bean.Employee">
                <association property="dept"
                             select="cn.itcast.mybatis.dao.DepartmentMapper.getDeptById"
                             column="d_id">
                </association>            
            </case>
    
            <!-- 1 表示男生, 如果是男生, 把last_name这一列赋值给 email -->
            <case value="1" resultType="cn.itcast.mybatis.bean.Employee">
                <id column="id" property="id"/>
                <result column="last_name" property="lastName"/>
                <result column="last_name" property="email"/>
                <result column="gender" property="gender"/>
            </case>
        </discriminator>
        <select id="getEmpByIdStep" resultMap="MyEmpDis">
            select * from tbl_employee where id=#{id}
        </select>
    
    
    // DpartmentMapper.xml
        <!-- 按照 id 查询部门 -->
        <select id="getDpetById" resultType="cn.itcast.mybatis.bean.Department">
            select id,dept_name departmentName from tbl_dept where id=#{id}
        </select>
    
        <!--
            resultMap 使用场景二: 查询部门的同时,查询出部门对应的所有员工信息
        -->
        <resultMap type="cn.itcast.mybatis.bean.Department" id="MyDept">
            <id column="did" property="id"/>
            <result column="dept_name" property="departmentName"/>
    
            <!--
                嵌套结果集的方式,使用 collection 标签定义关联的集合类型元素的封装规则
                collection: 定义关联集合类型属性的封装规则
                ofType: 指定集合里面元素的类型
             -->
             <collection property="emps" ofType="cn.itcast.mybatis.bean.Employee">
                <id column="eid" property="id"/>
                <result column="last_name" property="lastName"/>
                <result column="email" property="email"/>
                <result column="gender" property="gender"/>
             </collection>
        </resultMap>
    
        <!-- 查询部门的同时,查询部门下所有员工 -->
        <select id="getDeptByIdPlus" resultMap="MyDept">
            SELECT d.id did,d.dept_name dept_name,
                   e.id eid,e.last_name last_name,e.email email,e.gender gender
            FROM tbl_dept d
            LEFT JOIN tbl_employee e
            ON d.id=e.d_id
            WHERE d.id=#{id}
        </select>
    
        <!--
            collection: 分步查询
                向 collection 标签中传递多列的值: 将多列的值封装成 map 传递
                <collection property="..."
                            select="..."
                            colomn="{key1=column1,key2=column2...}"
                            fetchType="lazy": 默认使用延迟加载, 也可以禁掉:将lazy换为"eager">
                </collection>
        -->
        <resultMap type="cn.itcast.mybatis.bean.Department" id="MyDeptStep">
            <id column="id" property="id"/>
            <result column="dept_name" property="departmentName"/>
    
            <collection property="emps"
                        select="cn.itcast.mybatis.dao.EmployeeMapper.getEmpsByDeptId"
                        column="id"/>
            </collection>
        </resultMap>
        <select id="getDeptByIdStep" resultMap="MyDeptStep">
            select id,dept_name from tbl_dept where id=#{id}
        </select>
    
    
    // 测试类
    public class MyBatisTest{
        // 1. 获取 SqlSessionFactory 对象(略)
    
        @Test
        public void test() throws IOException{
            // 2. 获取 SqlSessionFactory 对象
            SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
    
            // 3. 获取 SqlSession 实例
            SqlSession openSession = sqlSessionFactory.openSession();
    
            try{
                // 4. 获取接口的实现类对象
                EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
    
                // 5. 查询,返回类型为 List
                List<Employee> list = mapper.getEmpsByLastNameLike("%e%");
                for(Employee emp : list){
                    System.out.println(emp);
                }
    
                // 返回类型为 Map
                Map<String,Object> map = mapper.getEmpByIdReturnMap(1);
                System.out.println(map);
    
                Map<String,Employee> map = mapper.getEmpByLastNameLikeReturnMap("%e%");
                System.out.println(map);
    
                // 查询员工的同时查询所在部门
                Employee emp = mapper.getEmpAndDept(2);
                System.out.println(emp);
    
            }finally{
                openSession.close();
            }
        }
    }
    

    参考资料

  • 相关阅读:
    MySQl数据约束练习
    MySQL查询实例
    网络通信协议简介(TCP与UDP)
    数据类型转换
    C++编译过的C代码为什么要用extern C
    hashtable
    以RB-tree为底层机制的几个关联式容器
    红黑树(RB-Tree)
    slist
    deque
  • 原文地址:https://www.cnblogs.com/linkworld/p/7792568.html
Copyright © 2011-2022 走看看