mybatis框架---分页插件PageHelper的使用方法

时间:2023-01-10 22:38:49

以前自己写分页时,需要自己写sql语句,并且进行分页判断之后才可以实现分页

目前Mybatis提供了分页插件,使用起来非常简便,适合于各类数据库分页,只需要在配置文件中配置数据库名即可,那么mybatis的插件作用在哪一环节呢?它主要作用在Executor执行器与mappedeStatement之间,也就是说mybatis可以在插件中获得要执行的sql语句,在sql语句中添加limit语句,然后再去对sql进行封装,从而可以实现分页处理

一:首先需要引入PageHelper的jar包。

如果使用了maven,那么只要在pom.xml中引入该插件即可,引入如下:

<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.4</version>
</dependency>

一: 在mybatis的全局配置文件SqlMapConfig.xml中配置该插件spring-mybatis.xml是这样配置:(数据源,分页拦截器)

顺便说说数据源的配置:

对于单数据源:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/pem"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>

多数据源:

<!--动态数据源配置 -->
<bean class="com.ixinnuo.credit.common.datasource.DynamicDataSource" id="dataSource">
<property name="targetDataSources"> //spring-jdbc-3.2.13.RELEASE.jar 依赖于spring对jdbc的支持
<map key-type="java.lang.String">
<entry value-ref="c_dataSource" key="c_ds"></entry>
<entry value-ref="r_dataSource" key="r_ds"></entry>
<entry value-ref="impalaDataSource" key="impala_ds"></entry>
<entry value-ref="sjcjDataSource" key="sjcj_ds"></entry>
</map>
</property>
<property name="defaultTargetDataSource" ref="c_dataSource">
</property>
</bean>


<!--配置数据库会话工厂-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="mapperLocations"> //定义mapper文件位置
<array>
<value>classpath*:com/ixinnuo/credit/**/mapping/**/*.xml</value>
</array>
</property>
<property name="typeAliasesPackage" value="com.ixinnuo.credit" /> //默认包的位置
<property name="plugins">
<array>
<!-- 性能拦截器,用于输出每条 SQL 语句及其执行时间 -->
<bean class="com.ixinnuo.credit.common.util.interceptor.PerformanceInterceptor"></bean>
<!-- MyBatis分页插件 -->
<bean class="com.github.pagehelper.PageHelper">
<property name="properties">
<value>
dialect=mysql或者为oracle
reasonable=true
          </value>
</property>
</bean>
<!-- MyBatis通用Mapper 拦截器 -->
<bean class="tk.mybatis.mapper.mapperhelper.MapperInterceptor">
       <property name="properties">
         <value>
         mappers=tk.mybatis.mapper.common.Mapper
         </value>
       </property>
   </bean>
</array>
</property>
</bean>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

我是在spring里配置的,还可以在mybatis-config.xml里配置,有兴趣的话可以百度下。

三:在执行sql前添加插件,完成分页功能  (在查询的sql语句执行之前,添加一行代码PageHelper.startPage(1,
10);

   /**
     * 开始分页  其中前两个参数是必须给的。
     *
     * @param pageNum      页码
     * @param pageSize     每页显示数量
     * @param count        是否进行count查询
     * @param reasonable   分页合理化,null时用默认配置
     * @param pageSizeZero true且pageSize=0时返回全部结果,false时分页,null时用默认配置
     */
    public static Page startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {
        Page page = new Page(pageNum, pageSize, count);
        page.setReasonable(reasonable);
        page.setPageSizeZero(pageSizeZero);
        SqlUtil.setLocalPage(page);
        return page;
    }

    第一个参数表示第几页,第二个参数表示每页显示的记录数。这样在执行sql后就会将记录按照语句中设置的那样进行分页。

     如果需要获取总记录数的话,需要PageInfo类的对象,这个对象可以获取总记录数、

下面看下后台实现代码,最重要的只要两句话

即在数据库查询之前告诉PageHelper开时分页:PageHelper.startPage(1,
10);
)以及查询完成得到totalPage返回

mapResult.put("totalPage", ((Page)resultList).getPages());,下面为一个完整方法代码:

@RequestMapping("getAllDetail")
public void getAllDetail(HttpServletRequest req,HttpServletResponse resp,Integer pageNum){
try {
ObjectMapper mapper = new ObjectMapper();
Map<String,Object> mapResult = new HashMap<String,Object>();

Integer pageSize = 8;
if (pageNum==null) {
pageNum = 1;
}

PageHelper.startPage(pageNum, pageSize,true);

List<DetailRecord> resultList = recordService.getDetail();
mapResult.put("totalPage", ((Page)resultList).getPages());

int count =  recordService.getCount();
mapResult.put("TOTAL_COUNT",count);
mapResult.put("result", "success");
mapResult.put("detail", resultList);

                       mapper.writeValue(resp.getWriter(), mapResult);

         }

前台实现代码(自动显示分页样式):

HtML部分

                     <div class="box-body">
<table id="datatable1" cellpadding="0" cellspacing="0" border="0" class="datatable table table-striped table-bordered table-hover">
<thead>
<tr style="height:35px;border-bottom:1px solid #555;">
  <th>序号</th>
<th>企业名称</th>
<th>纳税人识别号</th>
<th>查询时间</th>
<th>报告编号</th>
<th>历史报告</th>
</tr>
</thead>
<tbody id="lsmx-table">

//可以直接写<tr>标签或者handlebars模板动态渲染数据

</tbody>

</table>
<div class="pull-right"><a href="<%=basePath %>account/getDetailExcel">导出历史查询明细</a></div>
<!-- 分页 -->
<input type="hidden" id="pageNum" name="pageNum" />

<div class="text-center">
<div id="pagination" class="pagination" ></div>
<div>
<!-- 分页结束 -->

</div>

JS部分(整个完整的js页面)

(function($) {
//其中goPageNum初始传入1,随后会动态根据页数的跳转而变化,所以ajax中需要将该参数提交至后台。

window.lsmx = $.fn.qyzhkb = {
currentPage: 1,

recordDetail: function(goPageNum) {
$.ajax({
url: basePath + "account/getAllDetail?" + new Date().getTime(),
data:{
pageNum:goPageNum
},
dataType: "json",
type: "post",
success:function(data){
var result = data.result;
if(result === "success") {
var detail=data.detail
console.log(data.detail);
$("#total_count").text(data.TOTAL_COUNT);

var script=$("#template-lsmx").html();
var template=Handlebars.compile(script);

var result=template({items:detail});
$("#lsmx-table").html(result);
lsmx.bindDownload();     //数据渲染完成后触发bindDownload()函数
//分页开始
var totalPage = data.totalPage;
 //分页显示
if (totalPage === 0) {
totalPage = 1;
}

if (0 != totalPage) {
if (parseInt(totalPage) > 0) {
$("#
pagination").unbind();
$("#
pagination").bootpag({
total: parseInt(totalPage),
page: goPageNum,
maxVisible: 10,
leaps: true
}).bind("page", function(event, goPageNum) {
// 记录当前页

lsmx.currentPage = goPageNum;
lsmx.recordDetail(goPageNum);
});
}
}
   //分页结束


}
},
error:function(data){
console.log(data);
}
});
},

bindDownload:function(){
$(".download").on("click", function (){
var qymc = $(this).attr("title");
var idNum = $(this).attr("idNum");

$.ajax({ 
url:basePath+'account/downloadLog?'+ new Date().getTime(), 
data:{
qymc:qymc,
id:idNum,

},
type:'post',
success:function(data){
console.log(data);
console.log(data.address);
var jsonObj = JSON.parse( data ); 
var result = jsonObj.result;
var address = jsonObj.address;
console.log(result);
console.log(address);
if(result === "success") {
// $("<a style='disploy:none;' id='downfile_a' download href='"+address+"' />").click();
window.open(address); 
//window.location.href = address;

}else{
alert("没有历史报告可以下载。");
}
},
error:function(data){
console.log(data);
}

});
  });
}

}
})(jQuery);


/*页面初始化的时候调用方法*/
$(document).ready(function($){
lsmx.recordDetail(1);

});

Mybatis分页插件的优点:

现在来讲讲用了PageHelper之后的好处: 
那就是查询语句可以不用limit,但是就一点好处吗?自然不是。请接着往下看。

 
 
  • 1
  • 1


  • startPage是告诉拦截器说我要开始分页了。分页参数是这两个。








  •     startPage是告诉拦截器说我要开始分页了。分页参数是这两个。
后调用原来的Mybatis代码:

这里没有接收返回值,会不会觉得奇怪?实际上PageHelper已经自动接收了返回值。通过下面的代码可以取出返回值:

?
1 PageHelper.endPage();

同时endPage告诉拦截器说我结束分页了,不需要你了。

注意在你需要进行分页的Mybatis方法前调用PageHelper.startPage静态方法即可,紧跟在这个方法后的第一个Mybatis查询方法会被进行分页。


PageInfo这个类是插件里的类,这个类里面的属性还是值得看一看:

    //当前页
private int pageNum;
//每页的数量
private int pageSize;
//当前页的数量
private int size;
//排序
private String orderBy;

//由于startRow和endRow不常用,这里说个具体的用法
//可以在页面中"显示startRow到endRow 共size条数据"

//当前页面第一个元素在数据库中的行号
private int startRow;
//当前页面最后一个元素在数据库中的行号
private int endRow;
//总记录数
private long total;
//总页数
private int pages;
//结果集
private List<T> list;

//第一页
private int firstPage;
//前一页
private int prePage;
//下一页
private int nextPage;
//最后一页
private int lastPage;

//是否为第一页
private boolean isFirstPage = false;
//是否为最后一页
private boolean isLastPage = false;
//是否有前一页
private boolean hasPreviousPage = false;
//是否有下一页
private boolean hasNextPage = false;
//导航页码数
private int navigatePages;
//所有导航页号
private int[] navigatepageNums;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

使用PageInfo这个类,你需要将查询出来的list放进去:

PageInfo<CityList> p=new PageInfo<CityList>(list);
 
 
  • 1
  • 1

然后mv.addObject("page", p); 
这样在页面中就可以通过${page.nextPage}翻到下一页, 
${page.prePage}翻到上一页,  

2). PageHelper.startPage静态方法调用

例一:
SqlSession sqlSession = MybatisHelper.getSqlSession();
CountryMapper countryMapper = sqlSession.getMapper(CountryMapper.class);
try {
//获取第1页,10条内容,默认查询总数count
PageHelper.startPage(1, 10);

//紧跟着的第一个select方法会被分页
List<Country> list = countryMapper.selectIf(1);

//后面的不会被分页,除非再次调用PageHelper.startPage
List<Country> list2 = countryMapper.selectIf(null);
//list1
assertEquals(2, list.get(0).getId());
assertEquals(10, list.size());
//分页时,实际返回的结果list类型是Page<E>,如果想取出分页信息,需要强制转换为Page<E>,
//或者使用PageInfo类(下面的例子有介绍)
assertEquals(182, ((Page) list).getTotal());
//list2
assertEquals(1, list2.get(0).getId());
assertEquals(182, list2.size());
} finally {
sqlSession.close();
}