Mybatis聯(lián)表分頁查詢

在此之前請參考文章:
1、Spring Boot整合Mybatis框架在擴展文件編寫自己的sql語句
2、Mybatis單表分頁查詢

有兩張數(shù)據(jù)庫表user和user_info,他們是一對一關(guān)系,user_info以user_id關(guān)聯(lián)user表的id

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `username` varchar(20) DEFAULT NULL COMMENT '用戶名',
  `password` varchar(100) DEFAULT NULL COMMENT '密碼',
  `age` int(3) DEFAULT NULL COMMENT '年齡',
  `sex` varchar(1) DEFAULT NULL COMMENT '性別',
  `add_time` datetime DEFAULT NULL COMMENT '添加時間',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

CREATE TABLE `user_info` (
  `id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL COMMENT '用戶id,關(guān)聯(lián)user表',
  `phone` varchar(20) DEFAULT NULL COMMENT '手機號',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

以user_info為主表關(guān)聯(lián)user表進行查詢的語句如下:

SELECT
    *
FROM
user_info uf
LEFT JOIN `user` u ON u.id = uf.user_id
WHERE
    1 = 1
AND u.sex = '男'

下文將介紹兩種方式實現(xiàn)該語句的分頁查詢功能。


首先編寫dao層相關(guān)代碼

UserInfoMapperExt.xml文件

<?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.beibei.doc.dao.user.ext.UserInfoMapperExt" >
  <resultMap id="ExtResultMap" extends="com.beibei.doc.dao.user.UserInfoMapper.BaseResultMap" type="com.beibei.doc.model.user.UserInfo" >

  </resultMap>

<!-- 排序和分頁參數(shù) -->
<sql id="sort_limit">
    <if test="orderBy != null">
        order by ${orderBy}
    </if>
    <if test="limit != null">
        limit ${start} , ${limit}
    </if>
</sql>

 <!-- 需要查詢的字段 -->
 <sql id="UserInfo_Column_List" >
    *
 </sql>
 
 <!-- 查詢的表及查詢條件設(shè)置 -->
 <sql id="UserInfo_From_Where" >
    FROM
        user_info uf
    LEFT JOIN `user` u ON u.id = uf.user_id
    WHERE
        1 = 1
    <if test="map.sex != null">
        AND u.sex = '${map.sex}'
    </if>
 </sql>
 
<!-- 用戶信息分頁查詢 -->
<select id="selectUserInfoListPage" resultType="java.util.Map" parameterType="com.beibei.doc.util.Page">
    SELECT
    <include refid="UserInfo_Column_List"></include>
    <include refid="UserInfo_From_Where"></include>
    <include refid="sort_limit"></include>
</select>

<!-- 用戶信息數(shù)量查詢 -->
<select id="selectUserInfoListPageTotal" resultType="java.lang.Integer" parameterType="com.beibei.doc.util.Page">
    SELECT
        count(*)
    <include refid="UserInfo_From_Where"></include>
</select>

</mapper>

UserInfoMapperExt.java文件

package com.beibei.doc.dao.user.ext;

import com.beibei.doc.dao.base.BaseMapperExt;
import com.beibei.doc.model.user.UserInfo;
import com.beibei.doc.model.user.UserInfoExample;
import com.beibei.doc.util.Page;

public interface UserInfoMapperExt extends BaseMapperExt<UserInfo, UserInfoExample> {

}

注意:
1、其中UserInfoMapperExt.xml文件有兩個select,id分別是selectUserInfoListPage、selectUserInfoListPageTotal,前者是帶條件聯(lián)表查詢數(shù)據(jù)的sql語句,后者是和前者完全一樣的條件查詢數(shù)量的語句,其名稱一定要遵循前者名稱+Total的方式命名。

parameterType一定要設(shè)置為類com.beibei.doc.util.Page,這個類源碼請去看文章
Mybatis單表分頁查詢(http://www.lxweimin.com/p/67b3bfab7da3)

2、UserInfoMapperExt.java文件繼承BaseMapperExt.java。

有了dao層,就可以分別用兩種方式實現(xiàn)聯(lián)表分頁查詢了。


方式一:

1、在UserInfoMapperExt.java文件中定義兩個方法,與UserInfoMapperExt.xml文件中的selectUserInfoListPage、selectUserInfoListPageTotal一一對應(yīng),這樣子就可以通過這兩個方法直接執(zhí)行這兩個sql語句了。
需要注意的是方法的返回值要與sql語句中定義的resultType相對應(yīng),如resultType="java.util.Map"對應(yīng)的是List<Map<String, Object>>,因為selectUserInfoListPage查詢返回值是多條數(shù)據(jù),所以是一個list。
至于list的泛型可以是map,也可以是任意定義的一個類,這個類中的字段要與sql查詢結(jié)果集的字段對應(yīng),如果存在查詢結(jié)果中沒有的字段,需要在其getter方法上加注釋@Transient,查詢結(jié)果集中有,類中沒有的字段則無影響。

里面引用的的Page.java類請參考文章
Mybatis單表分頁查詢 http://www.lxweimin.com/p/67b3bfab7da3

/**
 * 用戶信息分頁查詢 
 * @param page
 * @return
 */
public List<Map<String, Object>> selectUserInfoListPage(Page<UserInfo, UserInfoExample> page);

/**
 * 用戶信息數(shù)量查詢 
 * @param page
 * @return
 */
public Integer selectUserInfoListPageTotal(Page<UserInfo, UserInfoExample> page);

2、service層代碼編寫

創(chuàng)建UserInfoService.java,繼承基類接口類BaseService.java

package com.beibei.doc.service.user;

import java.util.Map;

import com.beibei.doc.model.user.UserInfo;
import com.beibei.doc.model.user.UserInfoExample;
import com.beibei.doc.service.base.BaseService;
import com.beibei.doc.util.RespData;

public interface UserInfoService extends BaseService<UserInfo, UserInfoExample> {

    public RespData selectUserInfoListPage(Map<String, Object> param);
}

創(chuàng)建其實現(xiàn)類UserInfoServiceImpl.java,在里面實現(xiàn)分頁查詢方法selectUserInfoListPage,

package com.beibei.doc.service.user.impl;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.beibei.doc.dao.user.ext.UserInfoMapperExt;
import com.beibei.doc.model.user.UserInfo;
import com.beibei.doc.model.user.UserInfoExample;
import com.beibei.doc.service.base.impl.BaseServiceImpl;
import com.beibei.doc.service.user.UserInfoService;
import com.beibei.doc.util.Page;
import com.beibei.doc.util.RespData;

@Service
public class UserInfoServiceImpl extends BaseServiceImpl<UserInfo, UserInfoExample> implements UserInfoService {

    @Autowired
    private UserInfoMapperExt userInfoMapperExt;
    @Override
    public RespData selectUserInfoListPage(Map<String, Object> param) {
        RespData data = new RespData();
        Page<UserInfo, UserInfoExample> page = new Page<>(param);
        page.setMap(param);
        Integer total = userInfoMapperExt.selectUserInfoListPageTotal(page);
        page.setTotal(total);
        List<Map<String, Object>> list = userInfoMapperExt.selectUserInfoListPage(page);
        page.setList(list);
        data.setData(page.getPageData());
        return data;
    }
}

到這里分頁功能就實現(xiàn)了,在調(diào)用該方法時候參數(shù)param中要有 下一頁頁碼nextPage 和 每頁數(shù)量limit 兩個key的值,如果需要性別過濾,把sex的key值也放入param對象,然后調(diào)用page.setMap(param);來設(shè)置參數(shù),可以仔細研究UserInfoMapperExt.xml文件中的代碼片段

 <!-- 查詢的表及查詢條件設(shè)置 -->
 <sql id="UserInfo_From_Where" >
FROM
    user_info uf
LEFT JOIN `user` u ON u.id = uf.user_id
WHERE
    1 = 1
<if test="map.sex != null">
    AND u.sex = '${map.sex}'
</if>
 </sql>

方式二:

我的項目是和Spring Boot整合起來的,請先參考文章
Spring Boot一步步整合Mybatis框架(http://www.lxweimin.com/p/04aaa872ba30)
1、在配置類DataBaseConfig.java中加入SqlSessionTemplate的bean聲明

@Bean
public SqlSessionTemplate sqlSessionTemplate(){
    return new SqlSessionTemplate(this.sqlSessionFactory());
}

如果是配置文件的應(yīng)該是這樣子吧。

<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg ref="sqlSessionFactory" />
</bean>

2、在BaseService.java中定義方法

/**
 * <pre>
 * 關(guān)聯(lián)表分頁查詢接口
 * 說明:該方式查詢實際上是通過sqlSessionTemplate對象來
 *     調(diào)用在 MapperExt.xml 文件中定義的查詢sql語句, 因此要指定調(diào)用的select的id
 *     以及該select所在的MapperExt.xml文件所對應(yīng)的接口類(該類全名稱作為該MapperExt.xmll文件的命名空間),
 *     務(wù)必保證能夠正確拼接出完整的引用路徑。
 *     比如一個聯(lián)表查詢的sql: com.beibei.doc.dao.user.ext.UserInfoMapperExt.selectUserInfoListPage
 *     傳入?yún)?shù)是 selectId="selectUserInfoListPage", clazz=UserInfoMapperExt.class
 * </pre>
 * @param selectId 擴展文件MapperExt.xml中定義的查詢語句id
 * @param page 分頁對象
 * @param clazz 對應(yīng)的MapperExt接口類
 * @return
 */
public Page<M, E> selectByParamListPage(String selectId, Page<M, E> page, Class<? extends BaseMapperExt<M, E>> clazz);

在BaseServiceImpl.java中實現(xiàn)上面定義的方法,并且添加自動注入的SqlSessionTemplate對象屬性

@Autowired 
private SqlSessionTemplate sqlSessionTemplate;

@Override
public Page<M, E> selectByParamListPage(String selectId, Page<M, E> page, Class<? extends BaseMapperExt<M, E>> clazz) {
    String ext = clazz.toString().replace("interface ", "");
    Integer total = sqlSessionTemplate.selectOne(ext + "." + selectId + "Total", page);
    page.setTotal(total);
    List<?> list = sqlSessionTemplate.selectList(ext + "." + selectId, page);
    page.setList(list);
    return page;
}

3、調(diào)用該方法

    Page<UserInfo, UserInfoExample> page = new Page<>(param);
    page = userInfoService.selectByParamListPage("selectUserInfoListPage", page, UserInfoMapperExt.class);
    data.setData(page.getPageData());//獲取分頁查詢結(jié)果

總結(jié)

對比上面兩種方式可以發(fā)現(xiàn)方式一要在MapperExt.xml中定義和select的id相同的方法,比較麻煩。方式二則可以直接用select的id來調(diào)用BaseService中的selectByParamListPage方法就可以了,比較方便簡潔。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 1. 簡介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優(yōu)秀的...
    笨鳥慢飛閱讀 5,620評論 0 4
  • 1 引言# 本文主要講解JDBC怎么演變到Mybatis的漸變過程,重點講解了為什么要將JDBC封裝成Mybait...
    七寸知架構(gòu)閱讀 76,611評論 36 979
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,765評論 18 399
  • 心中很不能平靜。 地獄老師的課上,已有打碎器材的前科的我,這次做了成功的血涂片,還在同桌的顯微鏡上。 老師過來發(fā)現(xiàn)...
    DrChang閱讀 254評論 0 1
  • 一、不得因為喪事收受任何人的一文錢,但老朋友的不在此列; 二、趕快收殮,埋掉拉倒; 三、不要做任何關(guān)于紀念的事情;...
    椿樹閱讀 786評論 0 0