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