以前自己写分页时,需要自己写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>标签或者在<script>标签编写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>
<!-- 分页结束 -->
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是告诉拦截器说我要开始分页了。分页参数是这两个。
这里没有接收返回值,会不会觉得奇怪?实际上PageHelper已经自动接收了返回值。通过下面的代码可以取出返回值:
同时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(); }