注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

╰此情可待成追忆

当没有阳光时,我自己便是阳光,当没有快乐时,我自己便是快乐

 
 
 

日志

 
 

一步步学Mybatis-实现简单的分页效果逻辑 (5)  

2014-07-16 22:34:06|  分类: MyBatis+iBatis |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
http://www.blogjava.net/davidjefiny/archive/2013/12/25/408033.html

在前四章中我们已经基本完成了对单表的CRUD与多表联合查询方式的Mybatis操作与配置方式,今天这里要讲的是关于一个业务问题中我们常 碰到的分页问题。在开发web项目的时候我们经常会使用到列表显示,一般我们都会用一些常用的列表控件例如,datatables(个人感觉十分不 错),easy ui下面的那些封装好的表格控件。

  思路:在这些控件里要达到分页的效果,一般都会传2个参数,第一个是表示当前页的索 引(一般从0开始),第二个表示当前页展示多少条业务记录,然后将相应的参数传递给List<T> getList(PagenateArgs args)方法,最终实现数据库中的分页时候我们可以使用limit关键词(针对mysql)进行分页,如果是oracle或者sq server他们都有自带的rownum函数可以使用。

  针对上述思路,首先我们需要还是一如既往的在 demo.mybatis.model下面新建一个名为PagenateArgs的分页参数实体类与一个名为SortDirectionEnum的枚举 类,里面包含当前页面索引pageIndex, 当前页展示业务记录数pageSize, pageStart属性表示从第几条开始,(pageStart=pageIndex*pageSize)因为limit关键词用法是表示【limit 起始条数(不包含),取几条】,orderFieldStr排序字段,orderDirectionStr 排序方向,所以具体创建如下:


一步步学Mybatis-实现简单的分页效果逻辑 (5) - ╰此情可待成追忆 - ╰此情可待成追忆
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;
    }
}

 

一步步学Mybatis-实现简单的分页效果逻辑 (5) - ╰此情可待成追忆 - ╰此情可待成追忆
package david.mybatis.model;

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

    完成上面的步骤以后我们在IVisitorOperation接口类中继续添加一个方法public List<Visitor> getListByPagenate(PagenateArgs args),前几章中我们其实已经有getList方法了,这次的分页其实也就是在这个的基础上稍加改动即可,IVisitorOperation接口类 改动后如下所示:

一步步学Mybatis-实现简单的分页效果逻辑 (5) - ╰此情可待成追忆 - ╰此情可待成追忆
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);    
}

  接下来我们就要开始动手改动我们的VisitorMapper.xml配置文件了,新增一个<select>节点id与参数类型参照前几章的方式配置好,如下此处新增的id就为getListByPagenate,配置好以后如下

一步步学Mybatis-实现简单的分页效果逻辑 (5) - ╰此情可待成追忆 - ╰此情可待成追忆
<?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>

  在上面你会发现有类似,下图中的配置,这些是属于后面一章会讲述的动态SQL问题,现在可以暂时不管,这里面的字段属性都是针对PagenateArgs参数类中的属性名,保持一致

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

   在DemoRun类中创建测试方法:

一步步学Mybatis-实现简单的分页效果逻辑 (5) - ╰此情可待成追忆 - ╰此情可待成追忆
/*
 * 分页参数
 
*/
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.queryVisitorListWithPagenate(0100"id", SortDirectionEnum.DESC.toString());

运行后下测试结果,先按Id倒序排列,查的Visitor表一共有14条记录,

假设我们取在第2页取5条,执行下面也就是6-10条数据,这样传参数就行了

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

结果如下:

这样就自己实现了的一个分页逻辑啦~^0^,这里需要注意的就是我这边orderFieldStr字段是没有做过任何判断的,理论上要处理下防止错误了列名传进去,不过现在网上应该有现成封装好的东西,大家也可以去google下,这里只是给个思路演示下怎么用mybatis分页。

   完成这个后,因为是Mysql的关系所以在查询结果里他没有自带rownum序列ID,所以查看测试数据是第几条的时候可能不明显,不zao急,我们可 以自己动手丰衣足食改造下上面的方法,这里我重新在model包里新建一个一模一样的VisitorWithRn实体里面多带一个rownum参数持久化 返回的RownumID,如下:

一步步学Mybatis-实现简单的分页效果逻辑 (5) - ╰此情可待成追忆 - ╰此情可待成追忆
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));
    }
}

在 IVisitorOperation里面在新建一个名为 public List<VisitorWithRn> getListByPagenateWithRn(PagenateArgs args)的方法,同样我们需要在VisitorMapper中配置下相应<select>节点与脚本,此处唯一的不同就是需要改下sql脚 本,如下:

一步步学Mybatis-实现简单的分页效果逻辑 (5) - ╰此情可待成追忆 - ╰此情可待成追忆
<?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>

接下来剩下的就是如刚才在DemoRun下面添加测试方法,这里就不贴图了,完成后你可以看到刚刚的6-10条数据会变成如下

 今天的东西就讲到这里啦,下一章继续讲述Mybatis里面常用的动态SQL使用方法,希望对园子上的朋友们有帮助~^0^~

  评论这张
 
阅读(546)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017