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();
        }
    }
}

參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM