MyBatis-Plus實現(xiàn)跨表查詢并返回分頁
1. 概述
本文檔詳細(xì)介紹基于MyBatis-Plus框架實現(xiàn)的跨表查詢分頁功能。以供應(yīng)商物料查詢?yōu)槔?,展示如何通過多表關(guān)聯(lián)查詢并返回標(biāo)準(zhǔn)分頁對象的技術(shù)實現(xiàn)方案。
2. 技術(shù)棧
ORM框架: MyBatis-Plus
數(shù)據(jù)庫: MySQL(使用LIMIT進行分頁)
分頁組件: MyBatis-Plus Page對象
架構(gòu)模式: Repository + Mapper + XML三層架構(gòu)
3. 核心實現(xiàn)原理
3.1 分頁策略
采用手動分頁方式,分為兩步執(zhí)行:
查詢總數(shù): 執(zhí)行COUNT查詢獲取符合條件的總記錄數(shù)
查詢數(shù)據(jù): 根據(jù)偏移量(offset)和頁大小(size)查詢具體數(shù)據(jù)
3.2 為什么選擇手動分頁
跨表查詢涉及LEFT JOIN,MyBatis-Plus自動分頁可能存在性能問題
可以精確控制SQL語句,優(yōu)化查詢性能
支持復(fù)雜的動態(tài)條件拼接
4. 代碼實現(xiàn)詳解
4.1 參數(shù)對象設(shè)計
SupplierIdParam.java - 查詢參數(shù)封裝
@Getter
@Setter
@ToString
public class SupplierIdParam extends PageQueryParam {
private Long tenantId; // 租戶ID
private Long supplierId; // 供應(yīng)商ID
private String materialCategoryExternalCode; // 物料分類外部編碼
private String materialCategoryName; // 物料分類名稱
private String materialName; // 物料名稱
private String materialExternalCode; // 物料編碼
private String materialStatus; // 物料狀態(tài)
private String pricingType; // 定價類型
// ... 其他字段
}
關(guān)鍵點:
繼承PageQueryParam,包含currentPage和pageSize分頁參數(shù)
支持多維度動態(tài)查詢條件
使用包裝類型,便于判斷參數(shù)是否為空
4.2 領(lǐng)域?qū)ο笤O(shè)計
SupplierMaterialDO.java - 供應(yīng)商物料實體
@Getter
@Setter
@TableName(value = "t_supplier_material", autoResultMap = true)
public class SupplierMaterialDO implements BaseEntity {
private Long id;
private Long tenantId;
private Long supplierDataId;
private Long materialCategoryId;
private String materialCategoryExternalCode;
private String materialCategoryName;
private Long materialId;
private String externalCode;
private String name;
// ... 其他字段
}
關(guān)鍵點:
- 使用@TableName指定表名
- autoResultMap = true支持復(fù)雜結(jié)果映射
- 實現(xiàn)BaseEntity接口,包含通用字段
4.3 Repository層實現(xiàn)
SupplierMaterialRepository.java
@Repository
public class SupplierMaterialRepository extends HussarServiceImpl<SupplierMaterialMapper, SupplierMaterialDO> {
@Resource
private SupplierMaterialMapper supplierMaterialMapper;
public Page<SupplierMaterialDO> queryMaterialsBySupplierId(SupplierIdParam param) {
Long tenantId = param.getTenantId();
// 第一步:查詢總數(shù)
Long total = supplierMaterialMapper.queryMaterialsBySupplierIdCount(param, tenantId);
// 第二步:創(chuàng)建分頁對象
Page<SupplierMaterialDO> page = new Page<>(param.getCurrentPage(), param.getPageSize(), total);
// 第三步:查詢分頁數(shù)據(jù)
List<SupplierMaterialDO> supplierMaterialDOList =
supplierMaterialMapper.queryMaterialsBySupplierId(param, tenantId, page.offset(), page.getSize());
// 第四步:設(shè)置結(jié)果集
if (CollectionUtils.isNotEmpty(supplierMaterialDOList)) {
page.setRecords(supplierMaterialDOList);
}
return page;
}
}實現(xiàn)要點:
- 分離計數(shù)查詢: 單獨執(zhí)行COUNT查詢,避免查詢不必要的數(shù)據(jù)列
- 計算偏移量: 使用page.offset()方法自動計算OFFSET值
- 空值保護: 檢查查詢結(jié)果是否為空,避免設(shè)置null集合
- 租戶隔離: 所有查詢都攜帶tenantId,實現(xiàn)多租戶數(shù)據(jù)隔離
4.4 Mapper接口定義
SupplierMaterialMapper.java
@Mapper
public interface SupplierMaterialMapper extends BaseMapper<SupplierMaterialDO>, HussarMapper<SupplierMaterialDO> {
/**
* 查詢總數(shù)
*/
Long queryMaterialsBySupplierIdCount(@Param("param") SupplierIdParam param,
@Param("tenantId") Long tenantId);
/**
* 查詢分頁數(shù)據(jù)
*/
List<SupplierMaterialDO> queryMaterialsBySupplierId(@Param("param") SupplierIdParam param,
@Param("tenantId") Long tenantId,
@Param("offset") Long offset,
@Param("size") Long size);
}
設(shè)計說明:
- 使用@Param注解明確參數(shù)名稱,便于XML中引用
- 將offset和size作為獨立參數(shù)傳遞,提高SQL可讀性
- 返回類型分別為Long和List<SupplierMaterialDO>
4.5 MyBatis XML實現(xiàn)
SupplierMaterialMapper.xml
總數(shù)查詢SQL
<select id="queryMaterialsBySupplierIdCount" resultType="java.lang.Long">
SELECT count(*) AS total
FROM t_supplier_material tsm
LEFT JOIN t_material tm ON tsm.material_id = tm.id
WHERE tsm.delete_flag = '0'
AND tsm.tenant_id = #{tenantId}
<if test="param.supplierId != null and param.supplierId != ''">
AND supplier_id = #{param.supplierId}
</if>
<if test="param.materialCategoryExternalCode != null and param.materialCategoryExternalCode != ''">
AND tsm.material_category_external_code LIKE CONCAT('%', #{param.materialCategoryExternalCode}, '%')
</if>
<if test="param.materialCategoryName != null and param.materialCategoryName != ''">
AND tsm.material_category_name LIKE CONCAT('%', #{param.materialCategoryName}, '%')
</if>
<if test="param.materialName != null and param.materialName != ''">
AND tsm.name LIKE CONCAT('%', #{param.materialName}, '%')
</if>
<if test="param.materialExternalCode != null and param.materialExternalCode != ''">
AND tsm.external_code LIKE CONCAT('%', #{param.materialExternalCode}, '%')
</if>
<if test="param.materialStatus != null and param.materialStatus != ''">
AND tm.status = #{param.materialStatus}
</if>
<if test="param.pricingType != null and param.pricingType != ''">
AND tm.pricing_type = #{param.pricingType}
</if>
</select>分頁數(shù)據(jù)查詢SQL
<select id="queryMaterialsBySupplierId"
resultType="com.mdgyl.hussar.basic.supplier.masterdata.domain.SupplierMaterialDO">
SELECT tsm.*
FROM t_supplier_material tsm
LEFT JOIN t_material tm ON tsm.material_id = tm.id
WHERE tsm.delete_flag = '0'
AND tsm.tenant_id = #{tenantId}
<!-- 動態(tài)條件與COUNT查詢保持一致 -->
<if test="param.supplierId != null and param.supplierId != ''">
AND supplier_id = #{param.supplierId}
</if>
<if test="param.materialCategoryExternalCode != null and param.materialCategoryExternalCode != ''">
AND tsm.material_category_external_code LIKE CONCAT('%', #{param.materialCategoryExternalCode}, '%')
</if>
<!-- ... 其他動態(tài)條件 ... -->
ORDER BY tsm.id DESC
LIMIT #{offset}, #{size}
</select>SQL編寫要點:
- 表別名規(guī)范: 使用簡短且有意義的別名(如tsm、tm)
- 動態(tài)條件: 使用<if>標(biāo)簽實現(xiàn)條件可選,確保COUNT和DATA查詢條件一致
- 模糊查詢: 使用CONCAT('%', value, '%')實現(xiàn)LIKE模糊匹配
- 軟刪除過濾: 始終添加delete_flag = '0'條件
- 排序規(guī)則: 使用ORDER BY id DESC保證數(shù)據(jù)穩(wěn)定性
- LIMIT分頁: 使用LIMIT #{offset}, #{size}實現(xiàn)物理分頁
到此這篇關(guān)于MyBatis-Plus實現(xiàn)跨表查詢并返回分頁的文章就介紹到這了,更多相關(guān)MyBatis-Plus跨表查詢分頁內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決idea配置Tomcat Deployment沒有artifact選項的問題
今天在配置的時候tomcat deployment中卻找不到artifact,沒有artifact就不能打成war包上傳到服務(wù)器了,那么怎么解決沒有artifact選項的問題呢,今天通過本文給大家分享idea配置Tomcat Deployment沒有artifact選項的解決方案,一起看看吧2023-10-10
Java+Selenium實現(xiàn)控制瀏覽器的啟動選項Options
這篇文章主要為大家詳細(xì)介紹了如何使用java代碼利用selenium控制瀏覽器的啟動選項Options的代碼操作,文中的示例代碼講解詳細(xì),感興趣的可以了解一下2023-01-01
IntelliJ IDEA修改新建文件自動生成注釋的user名
今天小編就為大家分享一篇關(guān)于IntelliJ IDEA修改新建文件自動生成注釋的user名,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-10-10
Java一維數(shù)組和二維數(shù)組元素默認(rèn)初始化值的判斷方式
這篇文章主要介紹了Java一維數(shù)組和二維數(shù)組元素默認(rèn)初始化值的判斷方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08

