MyBatis複習(五):獲取多表關聯查詢結果

<select id="selectBlogMap" resultType="java.util.Map">
    select b.* , u.nick_name from t_blog b , t_user u
    where b.user_id = u.user_id
</select>
package com.cd.blog.config;

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 java.io.IOException;
import java.io.InputStream;

/**
 * @Author: 落葉無痕
 * @Date: 2020/5/15 16:45
 */
public class MyBatisUtils {

    /*MyBatisUtils工具類,目的是創建全局唯一的SqlSessionFactory對象*/


    //static屬於類不屬於對象,且全局唯一
    private static SqlSessionFactory sqlSessionFactory = null;

    //利用靜態塊在初始化類時初始化SqlSessionFactory
    static {
        InputStream input = null;
        try {
			// 使用字節流方式加載classpath下的mybatis-config.xml核心配置文件
            input = Resources.getResourceAsStream("mybatis-config.xml");
			// 初始化SqlSessionFactory對象,並解析mybatis-config.xml文件
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
        } catch (IOException e) {
            e.printStackTrace();
            //初始化錯誤時,拋出ExceptionInInitializerError異常通知調用者
            throw new ExceptionInInitializerError(e);
        }
    }

	// 創建SqlSession對象(SqlSession是JDBC的擴展類,專門用於與數據庫交互)
    public static SqlSession openSession(){
        return sqlSessionFactory.openSession();
    }

	// 釋放一個有效的SqlSession對象
    public static void closeSession(SqlSession sqlSession){
        if(sqlSession != null){
            sqlSession.close();
        }
    }

}
package com.cd.blog.config;

import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;
import java.util.Map;

/**
 * @Author: 落葉無痕
 * @Date: 2020/5/17 21:42
 */
public class TestMyBatisUtils {

    @Test
    public void demo(){
        SqlSession sqlSession = null;
        try{
            sqlSession = MyBatisUtils.openSession();
            List<Map> list = sqlSession.selectList("selectBlogMap");
            for(Map map : list){
                System.out.println(map);
            }
        }catch (Exception e){
            throw e;
        }finally {
            MyBatisUtils.closeSession(sqlSession);
        }
    }

}

1. 以java.util.Map作爲查詢結果,返回的數據是以鍵值對的格式返回的,鍵名是表字段名,鍵值是表字段的值。並且java.util.Map接口默認實現類是HashMap,根據HashMap的底層是hash表,HashMap的Key是根據Key的hash值來進行排序,hash值是一個不穩定的數字,所以各字段排序的結果就會出現亂序。


2. 爲保證返回結果的個字段的前後順序一致,需要將resultType查詢結果類型改爲java.util.LinkedHashMap,LinkedHashMap底層是鏈表,在進行數據提取時,是按照我們往裏插入數據時的先後順序進行保存,因此不會像HashMap一樣出現亂序現象。

<select id="selectBlogMap" resultType="java.util.LinkedHashMap">
    select b.* , u.nick_name from t_blog b , t_user u
    where b.user_id = u.user_id
</select>


總結:

  • 使用java.util.LinkedHashMap來接收數據,在我們的開發中是非常常見的。針對於多個表的關聯查詢,LinkedHashMap可以有效地幫助我們進行數據的擴展,使用起來非常靈活。

  • 關於javaType:

    • resultType的接收類型可以是實體類,實體類與表結構字段一致時可以自動封裝數據到實體類中
    • 當resultType爲Map時,查詢出來的數據是無序的。
    • resultType的類型爲Map / LinkedHashMap時多用於多表關聯查詢。

ResultMap結果集映射

1. ResultMap適用於java對象保存多表關聯查詢結果,可以將查詢結果映射爲複雜類型的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.cd.blog.dao.BlogDao">

    <!--配置實體類屬性與表字段的關係映射,結果集-->
    <resultMap id="blog" type="Blog">
        <!--主鍵字段用id配置,非主鍵字段用result配置 【property:實體類屬性名,column:表字段名】-->
        <id column="blog_id" property="blogId"/>
        <result column="title" property="title"/>
        <result column="content" property="content"/>
        <result column="create_time" property="createTime" javaType="java.util.Date"/>
        <result column="last_edit_time" property="lastEditTime" javaType="java.util.Date"/>
        <!--關聯用戶的結果集,用association標籤配置-->
        <!--從文章角度:文章對作者是一對一 -->
        <!--從作者角度: 作者對文章是一對多 -->
        <association column="user_id" property="user" javaType="User">
            <id column="user_id" property="userId"/>
            <result column="nick_name" property="nickName"/>
            <result column="user_Img" property="userImg"/>
        </association>
        <!--關聯分類的結果集,用association標籤配置-->
        <association column="type_id" property="type" javaType="Type">
            <id column="type_id" property="typeId"/>
            <result column="type_name" property="typeName"/>
        </association>
    </resultMap>
    
</mapper>

我們在獲取多表關聯查詢結果時,一般都會涉及到多個表的字段。這個時候,普通的實體類就無法滿足我們的需求了(普通實體類對象的屬性都是和對應表的字段一一對應的),當然我們也可以在實體類的基礎上進行擴展。
例如:

public class Blog {

    /*自增id*/
    private Integer blogId;
    /*文章標題*/
    private String title;
    /*文章內容*/
    private String content;
    /*文章標識: 原創、轉載、翻譯*/
    private String flag;
    /*瀏覽次數*/
    private int views;
    /*最近更新時間*/
    private Date lastEditTime;

//下面這些屬性用來在mybatis中進行關聯查詢
    /*作者:多對一關係*/
    private User user;
    /*分類:多對一關係*/
    private Type type;
}
<!--配置實體類屬性與表字段的關係映射,結果集-->
<resultMap id="blog" type="Blog">
    <!--主鍵字段用id配置,非主鍵字段用result配置 【property:實體類屬性名,column:表字段名】-->
    <id column="blog_id" property="blogId"/>
    <result column="title" property="title"/>
    <result column="content" property="content"/>
    <result column="flag" property="flag"/>
    <result column="views" property="views"/>
    <result column="last_edit_time" property="lastEditTime" javaType="java.util.Date"/>
    <!--關聯用戶的結果集,用association標籤配置-->
    <!--從文章角度:文章對作者是一對一 -->
    <!--從作者角度: 作者對文章是一對多 -->
    <association column="user_id" property="user" javaType="User">
        <id column="user_id" property="userId"/>
        <result column="nick_name" property="nickName"/>
        <result column="user_Img" property="userImg"/>
    </association>
    <!--關聯分類的結果集,用association標籤配置-->
    <association column="type_id" property="type" javaType="Type">
        <id column="type_id" property="typeId"/>
        <result column="type_name" property="typeName"/>
    </association>
</resultMap>


dto(Data Transfer Object)是一個特殊的java bean,名爲:數據傳輸對象。dto對象是對原始對象的擴展,用於數據的保存和傳遞。


前面提到,在保存和傳輸多表關聯查詢結果時,可以修改普通實體類進行擴展。平時開發的時候,很多程序員都是這麼幹的,包括我在內。但嚴格來講,這是代碼不規範的,因爲實體類和表字段的一一對應的,表中有多少個字段,對應的實體類就有多少個屬性。

此時,我們就可以通過dto數據傳輸對象來達到目的
例如:

public class BlogDTO {
	//文章
	private Blog blog;
    //作者
    private User user;
    //分類
    private Type type;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章