1. 程式人生 > >mybatis詳解-(16)分步查詢及延遲載入

mybatis詳解-(16)分步查詢及延遲載入

前面文章介紹了都是一個sql語句完成所有的查詢操作,包括在執行聯合查詢的時候也是一個sql語句完成查詢,然後將查詢結果通過resultMap進行封裝。mybatis也提供了分步查詢的功能,在完成一個操作之後,將查詢的結果使用到第二個三個查詢引數中完成所有的查詢。具體如何實現,還是結合示例做展示:

分步查詢

1)association
使用association實現分步查詢操作。

建立實體

Employee和Department

package org.mybatis.resultmap;

public class Employee {
    private Integer id;
    private
String lastName; private String email; private String gender; private Department department; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getLastName() { return lastName; } public
void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getGender() { return gender; } public void setGender(String gender) { this
.gender = gender; } public Department getDepartment() { return department; } public void setDepartment(Department department) { this.department = department; } @Override public String toString() { return "Employee [id=" + id + ", lastName=" + lastName + ", email=" + email + ", gender=" + gender + ", department=" + department + "]"; } }
package org.mybatis.resultmap;


public class Department {

    private Integer id;

    private String deptName;

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getDeptName() {
        return deptName;
    }
    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public String toString() {
        return "Department [id=" + id + ", deptName=" + deptName + "]";
    }

}

建立介面類
DepartmentMapper和EmployeeMapper

package org.mybatis.resultmap;

public interface DepartmentMapper {

    public Department getDeptById(Integer id);

}
package org.mybatis.resultmap;

public interface EmployeeMapper {

    /**
     * 分步查詢
     * @param id
     * @return
     */
    public Employee getEmpAndDeptByStep(Integer id);

}

建立對映配置檔案
resultmapmapper.xml對應Employee和resultmapdepartmentmapper.xml對應Department

<?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="org.mybatis.resultmap.EmployeeMapper">
    <!-- 分步查詢 -->
    <resultMap type="org.mybatis.resultmap.Employee" id="mstep">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="email" property="email"/>
        <result column="gender" property="gender"/>
        <!--org.mybatis.resultmap.DepartmentMapper.getDeptById為定義的DepartmentMapper的查詢介面-->
        <!--dept_id是Employee中對應Department的id值,作為傳遞引數-->
        <association property="department" select="org.mybatis.resultmap.DepartmentMapper.getDeptById" column="dept_id"></association>
    </resultMap>
    <select id="getEmpAndDeptByStep" resultMap="mstep">
        select * from mybatis_employee where id = #{id}
    </select>
</mapper>
<?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="org.mybatis.resultmap.DepartmentMapper">

    <select id="getDeptById" resultType="org.mybatis.resultmap.Department">
        select id,deptName from mybatis_department where id = #{id}
    </select>

</mapper>

建立主配置檔案
mybatis-config-resultmap.xml

<?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>

    <properties resource="db.properties"></properties>

    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <typeAliases>
        <!-- 為包下的所有類起別名,預設為類名大小寫(不區分大小寫) -->
        <package name="org.mybatis.resultmap"/>
    </typeAliases>


    <!-- 預設development是開發環境,如果改成test則表示使用測試環境 -->
    <environments default="dev_mysql">
        <environment id="dev_mysql">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="${mysql.driver}" />
                <property name="url" value="${mysql.url}" />
                <property name="username" value="${mysql.username}" />
                <property name="password" value="${mysql.password}" />
            </dataSource>
        </environment>

        <environment id="test_mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="${mysql.drivertest}" />
                <property name="url" value="${mysql.urltest}" />
                <property name="username" value="${mysql.usernametest}" />
                <property name="password" value="${mysql.passwordtest}" />
            </dataSource>
        </environment>

    </environments>

    <mappers>
        <mapper resource="mapper/resultmapmapper.xml"/>
        <mapper resource="mapper/resultmapdepartmentmapper.xml"/>
    </mappers>
</configuration>

建立測試類

package org.mybatis.resultmap;

import java.io.IOException;
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 org.junit.Test;

/**
 * 使用介面式程式設計
 */
public class MybatisTest {

    @Test
    public void testMybatis() {
        String resource = "mybatis-config-resultmap.xml";//全域性配置檔案

        InputStream inputStream = null;
        SqlSessionFactory sqlSessionFactory = null;
        SqlSession sqlSession = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            sqlSession = sqlSessionFactory.openSession();

            EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);

            //分步查詢
            Employee emp4 = mapper.getEmpAndDeptByStep(2);
            System.out.println(emp4.getLastName());
            System.out.println("`######");
            System.out.println(emp4.getDepartment());


            sqlSession.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
    }
}

執行結果:

DEBUG - ooo Using Connection [[email protected]]
DEBUG - ==> Preparing: select * from mybatis_employee where id = ?
DEBUG - ==> Parameters: 2(Integer)
DEBUG - ooo Using Connection [[email protected]]
DEBUG - ==> Preparing: select id,deptName from mybatis_department where id = ?
DEBUG - ==> Parameters: 2(Integer)
lisi
·######
Department [id=2, deptName=測試部]
DEBUG - Resetting autocommit to true on JDBC Connection [[email protected]]
DEBUG - Closing JDBC Connection [[email protected]]
DEBUG - Returned connection 1384722895 to pool.

與之前展示的不一樣的是本次操作傳送了兩次sql請求,先獲取到第一條資料的內容,然後從第一次請求獲取的結果中使用某個關聯值作為第二次查詢的引數。完成分步的查詢操作。

1)collection

使用collection實現分步查詢操作,跟使用association基本相似。

Employee和Department實體類不做任何修改。

DepartmentMapper新增查詢方法

public Department getDeptWithEmpByStep(Integer id);

EmployeeMapper新增查詢方法

/**
 * 通過部門id查詢Employee
 * @param id 部門id
 */
public List<Employee> getEmpByDeptId(Integer id);

Employee對應的resultmapmapper.xml配置檔案新增如下查詢方法:

<select id="getEmpByDeptId" resultType="org.mybatis.resultmap.Employee">
    select id,last_name,email,gender,dept_id from mybatis_employee where dept_id = #{deptId}
</select>

Department對應的resultmapdepartmentmapper.xml配置檔案新增如下查詢方法:

<!-- 分步查詢 collection-->
<resultMap type="org.mybatis.resultmap.Department" id="mstep2">
    <id column="did" property="id"/>
    <result column="deptName" property="deptName"/>
    <!-- 一個department對應多個employee -->
    <collection property="emps" select="org.mybatis.resultmap.EmployeeMapper.getEmpByDeptId" column="did">
        <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="getDeptWithEmpByStep" resultMap="mstep2">
    SELECT
        md.id did,
        md.deptName deptName
    FROM
        mybatis_department md
    WHERE
        md.id = #{id}
</select>

測試collection分步查詢

@Test
public void testMybatis() {
    String resource = "mybatis-config-resultmap.xml";//全域性配置檔案

    InputStream inputStream = null;
    SqlSessionFactory sqlSessionFactory = null;
    SqlSession sqlSession = null;
    try {
        inputStream = Resources.getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        sqlSession = sqlSessionFactory.openSession();

        DepartmentMapper mapper = sqlSession.getMapper(DepartmentMapper.class);

        Department dept2 = mapper.getDeptWithEmpByStep(2);
        System.out.println(dept2);
        System.out.println(dept2.getEmps());

        sqlSession.close();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
    }
}

測試結果

DEBUG - ooo Using Connection [[email protected]]
DEBUG - ==> Preparing: SELECT md.id did, md.deptName deptName FROM mybatis_department md WHERE md.id = ?
DEBUG - ==> Parameters: 2(Integer)
DEBUG - ooo Using Connection [[email protected]]
DEBUG - ==> Preparing: select id,last_name,email,gender,dept_id from mybatis_employee where dept_id = ?
DEBUG - ==> Parameters: 2(Integer)
Department [id=2, deptName=測試部]
[Employee [id=2, lastName=lisi, [email protected], gender=2], Employee [id=5, lastName=huanhuan, [email protected], gender=2], Employee [id=6, lastName=huanan, [email protected], gender=2]]
DEBUG - Resetting autocommit to true on JDBC Connection [[email protected]]
DEBUG - Closing JDBC Connection [[email protected]]
DEBUG - Returned connection 1282811396 to pool.

同樣傳送了兩次sql請求,資料封裝完成。
如果在第二步查詢的過程中需要傳遞多個引數,可以使用Map的形式進行傳遞,如:column=”did”可以寫成column=”{deptId=did}”。

2.延遲載入

在分步查詢的基礎之上,介紹一下延遲載入的內容。
關聯查詢的使用中,可能每次查詢只使用其中一個類的屬性,關聯類的屬性不需要使用,能夠不載入呢?mybatis提供延遲載入方案,設定延遲載入引數配置,可在使用的時候才載入某些資料。
如上面展示一次傳送兩個sql請求,將Employee和Department中的資料都查詢出來了。如果我想在使用Department的時候才去載入Department該如何實現呢?
在主配置檔案中<settings> 標籤新增如下配置:

<setting name="lazyLoadingEnabled" value="true" />
<setting name="aggressiveLazyLoading" value="false"/>

再次測試

DEBUG - ooo Using Connection [[email protected]]
DEBUG - ==> Preparing: select * from mybatis_employee where id = ?
DEBUG - ==> Parameters: 2(Integer)
lisi
`######
DEBUG - ooo Using Connection [[email protected]]
DEBUG - ==> Preparing: select id,deptName from mybatis_department where id = ?
DEBUG - ==> Parameters: 2(Integer)
Department [id=2, deptName=測試部]
DEBUG - Resetting autocommit to true on JDBC Connection [com.[email protected]]
DEBUG - Closing JDBC Connection [[email protected]]
DEBUG - Returned connection 1291113768 to pool.

結果顯示在使用Department之前,只發送了一個sql語句,當呼叫getDepartment()方法時才從後臺獲取資料。

相關推薦

mybatis-(16)分步查詢延遲載入

前面文章介紹了都是一個sql語句完成所有的查詢操作,包括在執行聯合查詢的時候也是一個sql語句完成查詢,然後將查詢結果通過resultMap進行封裝。mybatis也提供了分步查詢的功能,在完成一個操作之後,將查詢的結果使用到第二個三個查詢引數中完成所有的查詢。

【筆記】Mybatis高階查詢(小結)--巢狀查詢延遲載入

<association>與<collection>標籤一對一、一對多,多對多查詢時用到的屬性 property:對應實體類中的屬性名,必填項。 javaType:屬性對應的型別。 resultMap:可以直接使用現有

【筆記】Mybatis高階查詢(五)--使用resultMap的<collection>進行巢狀查詢延遲載入

下面例子通過<collection>實現一個通過使用者編號查詢使用者下面的角色及許可權的需求,支援延遲載入。下面以自下而上的過程來實現這樣的巢狀查詢功能。並且這個自下而上的過程中每一個方法都是獨立可用的方法。上層的結果都以下層方法為基礎。所有物件都設定為延遲載入。

【筆記】Mybatis高階查詢(三)--使用<association>標籤實現巢狀查詢延遲載入

<association>標籤實現巢狀查詢,需要用到以下屬性: select:另一個對映查詢的ID,Mybatis會額外執行這個查詢獲取巢狀物件的結果。 column:列名或別名,將主查詢中列的結果作為巢狀查詢的引數,配置方式如column=

Mybatis中《insert》返回map、list巢狀、association和collection分佈查詢延遲載入(懶載入)(按需載入)

本文目錄類容目錄結構: 一、select返回值 1、返回值記錄封裝為List 2、返回值記錄封裝為map 二、select_resultMap 1、自定義結果對映規則 2、關聯查詢_級聯屬性封裝結果,即<result column="did" pro

MyBatis分步查詢載入

分步查詢: 兩個pojo類: package com.itlike.domain; import lombok.Getter; import lombok.Setter; import lombok.ToString; @[email protected]@ToString p

Mybatis3.1-[tp_32-33]-_對映檔案_select_resultMap關聯查詢_association分步查詢_延遲載入

筆記要點出錯分析與總結 工程組織 1.定義介面   DepartmentMapper package com.dao; import com.bean.Department; public interface DepartmentMapper { pub

Mybatis3.1-[tp_34-35]-_對映檔案_select_resultMap關聯查詢_collection定義關聯集合封裝規則_collection分步查詢_延遲載入

筆記要點出錯分析與總結工程組織   1.定義介面 interface DepartmentMapper package com.dao; import com.bean.Department; public interface DepartmentMapper {

mybatis級聯查詢分步查詢延遲加載

enabled 4.2 res 標簽 mapper last pac mes 方式 級聯查詢: 1.Employee表: id;lastName;email; gender;d_id(外鍵關聯Department的ID) 2.Department表: id;deptNa

mybatis-(13)註解操作查詢

前面講述的內容中,基本都是按照同樣的步驟1)建立介面類,2)建立主配置檔案,3)建立介面對映檔案。在介面類中定義實現的介面功能,在對映配置檔案中寫具體的完成介面類容的sql語句,然後在主配置檔案中應用對映配置檔案操作相關的操作。mybatis也提供了一套通過介面

thinkphp5 資料庫和模型 之2 查詢構造器高階技巧

1、掌握查詢構造器對於掌握資料庫和模型的查詢操作非常關鍵 2、使用查詢構造器一般都是自動例項化查詢類,Db類的任何方法都會自動呼叫connect方法返回連線物件例項,然後呼叫連線物件的查詢構造器方法會自動例項化查詢類。 3、db助手函式預設每次呼叫都會重新連線資料庫(目的是

JAVAWEB開發之mybatis(二)——高階對映、查詢快取、mybatis與Spring整合以及懶載入的配置和逆向工程

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "ht

Mybatis系列(一)--持久層框架解決了什麼如何使用Mybatis

# 簡介 Mybatis 是一個持久層框架,它對 JDBC 進行了高階封裝,使我們的程式碼中不會出現任何的 JDBC 程式碼,另外,它還通過 xml 或註解的方式將 sql 從 DAO/Repository 層中解耦出來,除了這些基本功能外,它還提供了動態 sql、延遲載入、快取等功能。 相比 Hibern

Mybatis系列(二)--Mybatis如何載入配置初始化

簡介 Mybatis 是一個持久層框架,它對 JDBC 進行了高階封裝,使我們的程式碼中不會出現任何的 JDBC 程式碼,另外,它還通過 xml 或註解的方式將 sql 從 DAO/Repository 層中解耦出來,除了這些基本功能外,它還提供了動態 sql、延遲載入、快取等功能。 相比 Hibernate

MyBatis

esp resources myba 用法 管理 build oct ace 詳細信息 本文用例下載地址 http://files.cnblogs.com/files/gaofei-1/MyBatisDemo.rar 本文使用的是MySQL數據庫,所需SQL

mybatis (一)------JDBC

jdbc javax 發出 一段 true his 實例 用戶名 移植 1、什麽是MyBatis?   MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,

mybatis (二)------入門實例(基於XML)

ssi 開發模式 文件中 Coding import 拼接 upd baidu actor   通過上一小節,mybatis 和 jdbc 的區別:http://www.cnblogs.com/ysocean/p/7271600.html,我們對 mybatis有了一個大致

mybatis (七)------一對一、一對多、多對多

不變 角色 導入 ctu transacti stat 工程 build -1   前面幾篇博客我們用mybatis能對單表進行增刪改查操作了,也能用動態SQL書寫比較復雜的sql語句。但是在實際開發中,我們做項目不可能只是單表操作,往往會涉及到多張表之間的關聯操作。那麽我

mybatis ------動態SQL

soc int 表示 ssi 性別 ace cin override 博客 目錄 1、動態SQL:if 語句 2、動態SQL:if+where 語句 3、動態SQL:if+set 語句 4、動態SQL:choose(when,otherwise) 語句 5、動態SQL

css媒體查詢

rdp 多媒體類 str 表達式 來講 其中 使用 round block 簡介 媒體查詢(Media Queries)早在在css2時代就存在,經過css3的洗禮後變得更加強大bootstrap的響應式特性就是從此而來的. 簡單的來講媒體查詢是一種用於修飾css何時起作用