一步步學Mybatis-實現簡單的分頁效果邏輯 (5)

  在前四章中咱們已經基本完成了對單表的CRUD與多表聯合查詢方式的Mybatis操做與配置方式,今天這裏要講的是關於一個業務問題中咱們常碰到的分頁問題。在開發web項目的時候咱們常常會使用到列表顯示,通常咱們都會用一些經常使用的列表控件例如,datatables(我的感受十分不錯),easy ui下面的那些封裝好的表格控件。java

  思路:在這些控件裏要達到分頁的效果,通常都會傳2個參數,第一個是表示當前頁的索引(通常從0開始),第二個表示當前頁展現多少條業務記錄,而後將相應的參數傳遞給List<T> getList(PagenateArgs args)方法,最終實現數據庫中的分頁時候咱們可使用limit關鍵詞(針對mysql)進行分頁,若是是oracle或者sql server他們都有自帶的rownum函數可使用。mysql

  針對上述思路,首先咱們須要仍是一如既往的在demo.mybatis.model下面新建一個名爲PagenateArgs的分頁參數實體類與一個名爲SortDirectionEnum的枚舉類,裏面包含當前頁面索引pageIndex, 當前頁展現業務記錄數pageSize, pageStart屬性表示從第幾條開始,(pageStart=pageIndex*pageSize)由於limit關鍵詞用法是表示【limit 起始條數(不包含),取幾條】,orderFieldStr排序字段,orderDirectionStr 排序方向,因此具體建立以下:web

package david.mybatis.model;

/*
 * 分頁參數實體類
 */
public class PagenateArgs {
    private int pageIndex;
    private int pageSize;
    private int pageStart;
    private String orderFieldStr;
    private String orderDirectionStr;

    public PagenateArgs() {
        // TODO Auto-generated constructor stub
    }

    public PagenateArgs(int pageIndex, int pageSize, String orderFieldStr, String orderDirectionStr) {
        this.pageIndex = pageIndex;
        this.pageSize = pageSize;
        this.orderFieldStr = orderFieldStr;
        this.orderDirectionStr = orderDirectionStr;
        pageStart = pageIndex * pageSize;
    }

    public int getPageIndex() {
        return pageIndex;
    }

    public int getPageStart() {
        return pageStart;
    }

    public int getPageSize() {
        return pageSize;
    }

    public String orderFieldStr() {
        return orderFieldStr;
    }

    public String getOrderDirectionStr() {
        return orderDirectionStr;
    }
}
PagenateArgs分頁參數類
package david.mybatis.model;

/*
 * 排序枚舉
 */
public enum SortDirectionEnum {
    /*
     * 升序
     */
    ASC,
    
    /*
     * 降序
     */
    DESC
}
SQL排序枚舉

  完成上面的步驟之後咱們在IVisitorOperation接口類中繼續添加一個方法public List<Visitor> getListByPagenate(PagenateArgs args),前幾章中咱們其實已經有getList方法了,此次的分頁其實也就是在這個的基礎上稍加改動便可,IVisitorOperation接口類改動後以下所示:sql

package david.mybatis.demo;

import java.util.List;
import david.mybatis.model.PagenateArgs;
import david.mybatis.model.Visitor;
import david.mybatis.model.VisitorWithRn;

public interface IVisitorOperation {
    /*
     * 基礎查詢
     */
    public Visitor basicQuery(int id);

    /*
     * 添加訪問者
     */
    public int add(Visitor visitor);
    
    /*
     * 刪除訪問者
     */
    public int delete(int id);
    
    /*
     * 更新訪問者
     */
    public int update(Visitor visitor);
    
    /*
     * 查詢訪問者
     */
    public Visitor query(int id);
    
    /*
     * 查詢List
     */
    public List<Visitor> getList();
    
    /*
     * 分頁查詢List
     */
    public List<Visitor> getListByPagenate(PagenateArgs args);    
}
修改後的IVisitorOperation

  接下來咱們就要開始動手改動咱們的VisitorMapper.xml配置文件了,新增一個<select>節點id與參數類型參照前幾章的方式配置好,以下此處新增的id就爲getListByPagenate,配置好之後以下數據庫

<?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="david.mybatis.demo.IVisitorOperation">
    <!-- useGeneratedKeys="true"表明是否使用自增加序列, keyProperty="Id"指定自增加列是哪一列, parameterType="Visitor"指定IVisitorOperation接口類中定義中所傳的相應類型 -->
    <insert id="add" parameterType="Visitor" useGeneratedKeys="true"
        keyProperty="Id">
        insert into Visitor (Name, Email, Status, CreateTime)
        values (#{name}, #{email}, #{status}, #{createTime})
    </insert>
    <delete id="delete" parameterType="int">
        delete from Visitor where
        status>0 and id = #{id}
    </delete>
    <update id="update" parameterType="Visitor">
        update Visitor set Name =
        #{name}, Email=#{email}, Status=#{status} where id=#{id} and Status>0;
    </update>
    <select id="query" parameterType="int" resultType="Visitor">
        select Id,
        Name, Email, Status, CreateTime from visitor where id=#{id} and
        Status>0 order by Id
    </select>
    <select id="basicQuery" parameterType="int" resultType="Visitor">
        select *
        from visitor where id=#{id} and
        Status>0 order by Id
    </select>
    <select id="getList" resultMap="visitorRs">
        <include refid="getListSql" />
    </select>
    <sql id="getListSql">
        select * from Visitor where
        status>0
    </sql>
    <!-- 如下爲新增部分用來分頁,orderBySql這個提取出來是爲了後面有示例複用 -->
    <resultMap type="Visitor" id="visitorRs">
        <id column="Id" property="id" />
        <result column="Name" property="name" />
        <result column="Email" property="email" />
        <result column="Status" property="status" />
        <result column="CreateTime" property="createTime" />
    </resultMap>
    <select id="getListByPagenate" parameterType="PagenateArgs"
        resultType="Visitor">
        select * from (
        <include refid="getListSql" /> <include refid="orderBySql"/>
        ) t <!-- #{}表示參數化輸出,${}表示直接輸出不進行任何轉義操做,本身進行轉移 -->
        <if test="pageStart>-1 and pageSize>-1">
            limit #{pageStart}, #{pageSize}
        </if>
    </select>
    <sql id="orderBySql">
        order by ${orderFieldStr} ${orderDirectionStr}
    </sql>
</mapper>
修改後的VisitorMapper配置

  在上面你會發現有相似,下圖中的配置,這些是屬於後面一章會講述的動態SQL問題,如今能夠暫時無論,這裏面的字段屬性都是針對PagenateArgs參數類中的屬性名,保持一致session

<if test="pageStart>-1 and pageSize>-1">
    limit #{pageStart}, #{pageSize}
</if>

   在DemoRun類中建立測試方法:mybatis

/*
 * 分頁參數
 */
public static void queryVisitorListWithPagenate(int pageIndex, int pageSize, String orderField, String orderDire) {
    PagenateArgs args = new PagenateArgs(pageIndex, pageSize, orderField, orderDire);
    SqlSession session = MybatisUtils.getSqlSession();
    IVisitorOperation vOperation = session.getMapper(IVisitorOperation.class);
    List<Visitor> visitors = vOperation.getListByPagenate(args);
    for (Visitor visitor : visitors) {
        System.out.println(visitor);
    }
    MybatisUtils.closeSession(session);
    MybatisUtils.showMessages(CRUD_Enum.List, visitors.size());
}
DemoRun分頁
DemoRun.queryVisitorListWithPagenate(0, 100, "id", SortDirectionEnum.DESC.toString());

運行後下測試結果,先按Id倒序排列,查的Visitor表一共有14條記錄,oracle

假設咱們取在第2頁取5條,執行下面也就是6-10條數據,這樣傳參數就好了app

DemoRun.queryVisitorListWithPagenate(1, 5, "id", SortDirectionEnum.DESC.toString());

結果以下:ide

這樣就本身實現了的一個分頁邏輯啦~^0^,這裏須要注意的就是我這邊orderFieldStr字段是沒有作過任何判斷的,理論上要處理下防止錯誤了列名傳進去,不過如今網上應該有現成封裝好的東西,你們也能夠去google下,這裏只是給個思路演示下怎麼用mybatis分頁。

  完成這個後,由於是Mysql的關係因此在查詢結果裏他沒有自帶rownum序列ID,因此查看測試數據是第幾條的時候可能不明顯,不zao急,咱們能夠本身動手豐衣足食改造下上面的方法,這裏我從新在model包裏新建一個如出一轍的VisitorWithRn實體裏面多帶一個rownum參數持久化返回的RownumID,以下:

package david.mybatis.model;

import java.text.SimpleDateFormat;
import java.util.Date;

public class VisitorWithRn {
    private int id;
    private String name;
    private String email;
    private int status;
    private Date createTime;
    private int rownum;

    public VisitorWithRn() {
        // TODO Auto-generated constructor stub
        createTime = new Date();
    }

    public VisitorWithRn(String name, String email) {
        this.name = name;
        this.email = email;
        this.setStatus(1);
        this.createTime = new Date();
    }

    public int getId() {
        return id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getEmail() {
        return email;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public int getRownum() {
        return rownum;
    }

    public void setRownum(int rownum) {
        this.rownum = rownum;
    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return String.format("{Rownum:%d, Id: %d, Name: %s, CreateTime: %s}", rownum, id, name,
                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(createTime));
    }
}
VisitWithRn

在IVisitorOperation裏面在新建一個名爲 public List<VisitorWithRn> getListByPagenateWithRn(PagenateArgs args)的方法,一樣咱們須要在VisitorMapper中配置下相應<select>節點與腳本,此處惟一的不一樣就是須要改下sql腳本,以下:

<?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="david.mybatis.demo.IVisitorOperation">
    <!-- useGeneratedKeys="true"表明是否使用自增加序列, keyProperty="Id"指定自增加列是哪一列, parameterType="Visitor"指定IVisitorOperation接口類中定義中所傳的相應類型 -->
    <insert id="add" parameterType="Visitor" useGeneratedKeys="true"
        keyProperty="Id">
        insert into Visitor (Name, Email, Status, CreateTime)
        values (#{name}, #{email}, #{status}, #{createTime})
    </insert>
    <delete id="delete" parameterType="int">
        delete from Visitor where
        status>0 and id = #{id}
    </delete>
    <update id="update" parameterType="Visitor">
        update Visitor set Name =
        #{name}, Email=#{email}, Status=#{status} where id=#{id} and Status>0;
    </update>
    <select id="query" parameterType="int" resultType="Visitor">
        select Id,
        Name, Email, Status, CreateTime from visitor where id=#{id} and
        Status>0 order by Id
    </select>
    <select id="basicQuery" parameterType="int" resultType="Visitor">
        select *
        from visitor where id=#{id} and
        Status>0 order by Id
    </select>
    <select id="getList" resultMap="visitorRs">
        <include refid="getListSql" />
    </select>
    <sql id="getListSql">
        select * from Visitor where
        status>0
    </sql>
    <resultMap type="Visitor" id="visitorRs">
        <id column="Id" property="id" />
        <result column="Name" property="name" />
        <result column="Email" property="email" />
        <result column="Status" property="status" />
        <result column="CreateTime" property="createTime" />
    </resultMap>
    <select id="getListByPagenate" parameterType="PagenateArgs"
        resultType="Visitor">
        select * from (
        <include refid="getListSql" /> <include refid="orderBySql"/>
        ) t <!-- #{}表示參數化輸出,${}表示直接輸出不進行任何轉義操做,本身進行轉移 -->
        <if test="pageStart>-1 and pageSize>-1">
            limit #{pageStart}, #{pageSize}
        </if>
    </select>
    <!--提煉出來爲了2個示例共用下 -->
    <sql id="orderBySql">
        order by ${orderFieldStr} ${orderDirectionStr}
    </sql>
    <!-- 帶rownum的SQL腳本書寫方式 -->
    <resultMap type="VisitorWithRn" id="visitorWithRnRs">
        <id column="Id" property="id" />
        <result column="Name" property="name" />
        <result column="Email" property="email" />
        <result column="Status" property="status" />
        <result column="CreateTime" property="createTime" />
        <result column="Rownum" property="rownum" />
    </resultMap>
    <select id="getListByPagenateWithRn" resultMap="visitorWithRnRs">
        <!-- #{}表示參數化輸出,${}表示直接輸出不進行任何轉義操做,本身進行轉移 -->
        select t.Rownum, t.Id, t.Name, t.Email, t.Status, t.CreateTime from (<include refid="getListSqlContainsRn" /> <include refid="orderBySql"/>) t
        <if test="pageStart>-1 and pageSize>-1">
            limit #{pageStart}, #{pageSize}
        </if>
    </select>
    <sql id="getListSqlContainsRn">
        select @rownum:=@rownum+1 Rownum,
        result.id, result.name, result.email, result.status, result.createTime
        FROM (
        select @rownum:=0, Visitor.* from Visitor where
        status>0) result
    </sql>
</mapper>
添加具備Rn效果的配置文件

接下來剩下的就是如剛纔在DemoRun下面添加測試方法,這裏就不貼圖了,完成後你能夠看到剛剛的6-10條數據會變成以下

 今天的東西就講到這裏啦,下一章繼續講述Mybatis裏面經常使用的動態SQL使用方法,但願對園子上的朋友們有幫助~^0^~

相關文章
相關標籤/搜索