MyBatis,MySql儲存過程分頁查詢
阿新 • • 發佈:2019-02-19
前言
如果涉及到同一臺機器上不同庫不同表的關聯查詢,可以通過 資料庫名.表名 的形式來進行跨庫查詢,若不用外掛,這時可以通過儲存過程來完成查詢。
編寫儲存過程
以學生資訊查詢為例,例如有兩個庫。
學生庫student(學生資訊表 stu_info)
CREATE TABLE `stu_info` (
`id` varchar(64) NOT NULL,
`name` varchar(64) NOT NULL COMMENT '學生姓名',
`teacher_id` varchar(64) DEFAULT NULL COMMENT '教師id',
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
教師庫teacher(教師資訊表 teacher_info)
CREATE TABLE `teacher_info` (
`id` varchar(64) NOT NULL,
`name` varchar(64) NOT NULL COMMENT '教師姓名',
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
其中每個學生有一個指導老師,每個指導老師可以指導多個學生。
先要查詢出所有學生的名字及其指導教師。由於分頁引數是呼叫方傳入,因此分頁引數通過佔位符(?,?)來替代,並使用MySql Prepared SQL Statement[1]。最終儲存過程如下。
CREATE PROCEDURE test_proc_paging(
IN pageNum int,
IN pageSize int
)
BEGIN
SET @pageSize = pageSize;
SET @pageNum = pageNum;
PREPARE s1 FROM "
select s.name as stu,t.name as teacher from student.stu_info s left join teacher.teacher_info t on s.teacher_id = t.id
limit ?,?"
EXECUTE s1 USING @pageNum,@pageSize;
DEALLOCATE PREPARE s1;
SELECT FOUND_ROWS() as recordCounts;
END
- PREPARE s1 … 定義prepared statement s1
- EXECUTE s1 … 執行s1,並用引數替換佔位符
- DEALLOCATE PREPARE s1… 釋放prepared statement
- SELECT FOUND_ROWS() as recordCounts; 返回總記錄數
最終呼叫儲存過程會返回兩個結果,一個是分頁查詢的結果,一個是總的結果數。
MyBatis呼叫儲存過程
StuInfoDao定義為,其中StuInfoForm 包含了查詢引數,即兩個分頁引數。注意由於呼叫的儲存過程返回多個結果集,因此DAO中的查詢語句返回結果為List<Object>
public interface StuInfoDao {
public List<Object> queryStuByProc(StuInfoForm form);
}
Mybatis mapper.xml 定義,由於返回結果包含兩個結果集,因此定義了兩個ResultMap,並在select查詢中指定了兩個ResultMap[2]。
<resultMap type="java.lang.Integer" id="recordCounts">
<result column="recordCounts" jdbcType="INTEGER" />
</resultMap>
<resultMap id="dtoResultMap" type="com.fengdai.report.model.Certification">
<result column="stu" jdbcType="VARCHAR" property="stu" />
<result column="teacher" jdbcType="VARCHAR" property="teacher" />
</resultMap>
<select id="queryStuByProc" resultMap="dtoResultMap,recordCounts" statementType="CALLABLE" >
{
CALL test_proc_paging(#{pageNum,jdbcType=INTEGER},
#{pageSize,jdbcType=INTEGER})
}
</select>
查詢與返回結果的處理
返回結果,那麼通過如下的程式碼獲取結果,及總記錄數,然後填入返回物件的成員中,最後返回給前端即可。
form.setPageNum((form.getPageNum()-1)*form.getPageSize());
List<Object> result = certificationDao.queryStuByProc(form);
// 結果
List<Object> result = list.get(0);
// 總記錄數
Integer size = ((ArrayList<Integer>)list.get(1)).get(1);
form中的pageNum定義了頁號,pageSize定義的單頁大小,因此在查詢前需要將pageNum,pageSize轉換為相應的分頁查詢引數。
例如 查第5頁,每頁10條,那麼sql中的limit偏移就是 limit (5-1)*10,10