序
Mybatis pagehelper 分页查询的原理:
1.前端通过ajax传递参数currentPage(当前页码)和perPageNum(每页显示的数据记录数)到后台;
2.后台接受上述两个参数,在传统的查询(SELECT * FROM tablename)之前通过拦截器原理改写查询语句,改成
(SELECT * FROM tablename limit m,n),其中m=(currentPage-1)*perPageNum,n=perPageNum,再进行查询,从而实现物理分页查询的作用。
3.查询出来的结果集是一个list,为了前端更好地处理数据,我们使用mybatis pagehelper 定义的的pageInfo这个bean来封装list数据,然后返回前台。
4.分页查询是在上一节课mybatis generator逆向工程自动生成代码的基础上完成,需要代码的点击我。
一、添加依赖、配置过滤器
1.在pom.xml中添加pagehelper的依赖:
<!--pagehelper分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.0.3</version>
</dependency>
2.因为我们的分页查询基于SSM框架,故分页插件的过滤器配置在spring-mybatis.xml(或applicationContent-mybatis.xml)中:
<!--pagehelper插件配置 -->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<!--使用下面的方式配置参数,一行配置一个 -->
<value>
<!--数据库采用mysql -->
helperDialect=mysql
<!-- 和startPage中的pageNum效果一样-->
offsetAsPageNum=true
<!-- 设置为true时,使用RowBounds分页会进行count查询 -->
rowBoundsWithCount=true
<!-- 设置为true时,如果pageSize=0或者RowBounds.limit=0就会查询出全部的结果 -->
<!-- (相当于没有执行分页查询,但是返回结果仍然是Page类型)-->
pageSizeZero=true
<!-- 启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页 -->
<!-- 禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 -->
reasonable=true
</value>
</property>
</bean>
</array>
</property>
二、(后端1/2)编写Dao层、Service层接口,并实现
Dao层接口定义:UserMapper.java
package com.ssm.dao;
import com.ssm.model.User;
import com.ssm.model.UserExample;
import java.util.List;
import org.apache.ibatis.annotations.Param;
public interface UserMapper {
long countByExample(UserExample example);
int deleteByExample(UserExample example);
int deleteByPrimaryKey(Integer id);
int insert(User record);
int insertSelective(User record);
List<User> selectByExample(UserExample example);
User selectByPrimaryKey(Integer id);
int updateByExampleSelective(@Param("record") User record, @Param("example") UserExample example);
int updateByExample(@Param("record") User record, @Param("example") UserExample example);
int updateByPrimaryKeySelective(User record);
int updateByPrimaryKey(User record);
}
Dao层接口实现:UserMapper.xml (鉴于代码太多,只贴出查询的代码)
<select id="selectByExample" parameterType="com.ssm.model.UserExample"
resultMap="BaseResultMap">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
from user_t
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer"
resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from user_t
where id = #{id,jdbcType=INTEGER}
</select>
Service层接口定义:UserService.java
package com.ssm.service;
import java.util.List;
import com.ssm.model.User;
import com.ssm.model.UserExample;
public interface UserService {
// 利用id查询用户名,非分页查询
public User getUserById(int userId);
// 通过姓名进行模糊条件查询,分页查询
List<User> getUserInfoByName(UserExample example);
}
UserServiceImpl.java 接口实现类
package com.ssm.service.impl;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ssm.dao.UserMapper;
import com.ssm.model.User;
import com.ssm.model.UserExample;
import com.ssm.service.UserService;
@Service("userService")
public class UserServiceImpl implements UserService {
@Resource
@Autowired
private UserMapper userMapper;
public User getUserById(int userId) {
// TODO Auto-generated method stub
return this.userMapper.selectByPrimaryKey(userId);
}
@Override
public List<User> getUserInfoByName(UserExample example) {
// TODO Auto-generated method stub
return this.userMapper.selectByExample(example);
}
}
三、后端(2/2)编写controller类(接收前端请求,调用service层业务逻辑,完成查询并返回结果给前端)
Controller类:UserController.java
package com.ssm.controller;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ssm.model.User;
import com.ssm.model.UserExample;
import com.ssm.service.UserService;
@Controller
@RequestMapping("/user")
public class QueryUserController {
@Autowired
private UserService userService;
@Transactional(readOnly = false)
@RequestMapping(value = "/queryByXh", method = RequestMethod.POST)
public @ResponseBody User QueryUserInfoByXh(@RequestParam(value = "sno", required = false) String sno) {
ModelAndView modelAndView = new ModelAndView();
int id = Integer.parseInt(sno);
User user = userService.getUserById(id);
modelAndView.addObject("user", user);
return user;
}
@RequestMapping(value = "/")
public String IndexUser(@RequestParam(value = "name", required = false) String name) {
return "user";
}
@RequestMapping(value = "/queryByXm", method = RequestMethod.POST)
@ResponseBody
//这里接收前端最好使用@RequestBody Map<String,String> map,不然像这个参数太多的话显得代码太啰嗦
//使用@RequestBody接收参数需要在spring-mvc.xml中开启注解支持 <tx:annotation-driven/>
//没有用过@RequestBody注解的同学可以去试试,这个真的非常强大,
public PageInfo<User> queryUserInfoByName(@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "currentPage", required = false) int currentPage,
@RequestParam(value = "perPageNum", required = false) int perPageNum) {
UserExample userExample = new UserExample();
if (name != null ) {
name = "%" + name + "%";//实现按姓名查询的模糊查法
}
userExample.createCriteria().andUserNameLike(name);
//使用Mybatis pagehelper进行分页,PageHelper.startPage()方法只对他下面紧接他的查询语句进行分页
PageHelper.startPage(currentPage, perPageNum);
List<User> list = userService.getUserInfoByName(userExample);
PageInfo<User> pageInfo = new PageInfo<User>(list);//封装结果集到PageInfo bean
return pageInfo;
}
}
四、(前端)jsp页面的编写
user.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
<link rel="stylesheet" href="<%=path %>/css/style.css" />
<link rel="stylesheet" type="text/css" href="<%=path%>/css/pageNav.css" />
<script type="text/javascript" src="<%=path%>/js/pageNav.js"></script>
<script type="text/javascript" src="<%=path%>/js/jquery-3.1.1.min.js"></script>
</head>
<body>
查询页面
<br> 学号:
<input type="text" class="t1" id="sno" name="sno" placeholder="输入学号">
<input type="button" onclick="queryUserInfoByXh()" value="query">
姓名:
<input type="text" class="t1" id="name" name="name" placeholder="输入姓名">
<input type="button" onclick="queryUserInfoByXm(1)" value="query">
<br>
<input type="hidden" id="hidden" value="">
<!-- 用于表格显示数据 -->
<table class="table" id='tabletest'>
<tr>
<th>学号</th>
<th>姓名</th>
<th>密码</th>
<th>年龄</th>
</tr>
</table>
<nav aria-label="Page navigation" class="page-nav-outer" id="PageNavId"></nav>
<!-- script函数处理块 -->
<script>
var path = '<%=path%>';
var pageNavObj = null;//用于储存分页对象
/* 实现将搜索框提示文字当鼠标点击搜索框是文字自动清除功能 */
$(".t1").focus(function() {
$(".t1").val("");
});
/*处理当页面加载时,同时加载需要请求的数据信息*/
$(document).ready(function() {
queryUserInfoByXm(1);
});
function queryUserInfoByXh() {
var sno = $("#sno").val();
$.ajax({
type : 'post',
//contentType : 'application/json',
url : path + '/user/queryByXh',
//processData : false,
dataType : 'json',
data : {
sno : sno
},
success : function(data) {
$("#tabletest").empty();//每次检索信息前先把当前显示数据清空,不然叠加显示
var tr;
tr='<td>'+data.id+'</td>'+'<td>'+data.userName+'</td>'+'<td>'+data.password+'</td>'+'<td>'+data.age+'</td>'
$("#tabletest").append('<tr>'+tr+'</tr>')
},
error : function() {
alert("学号不存在!");
}
});
}
/*
*根据姓名为条件进行模糊查询/精准查询
*分页查询
*/
function queryUserInfoByXm(clickPage) {
var name = $("#name").val();
$.ajax({
type : 'post',
//contentType : 'application/json',
url : path + '/user/queryByXm',
//processData : false,
dataType : 'json',
data : {
"currentPage":clickPage,
"perPageNum":10,
"name" : name
//"name" : name 也可以
},
success : function(data) {
var page;
$("#tabletest").empty("");
//
pageNavObj = new PageNavCreate("PageNavId",{pageCount:data.pages,currentPage:clickPage,perPageNum:5});//创建分页查询页码导航栏
if(data.length==0){
alert("无信息记录");
}
for(i in data.list) //i是数组的索引 data是数据列表
{
var tr;
tr='<td>'+data.list[i].id+'</td>'+'<td>'+data.list[i].userName+'</td>'+'<td>'+data.list[i].password+'</td>'+'<td>'+data.list[i].age+'</td>'
$("#tabletest").append('<tr>'+tr+'</tr>')
}
/*
*加载分页查询页面属性:当前页,总页数,总记录数
*/
page='<td>当前第'+data.pageNum+'页.总共'+ data.pages+'页.一共'+ data.total+'条记录'
$("#tabletest").append('<tr>'+page+'</tr>')
/*目的的当点击分页上的页码按钮时发起查询操作*/
pageNavObj.afterClick(queryUserInfoByXm);
},
error : function(){
alert("查询失败");
}
});
}
</script>
</body>
</html>
分页查询页码导航的封装 :
设计页码导航栏的时候,首先想到的是高复用性,因为分页查询我们会在很多查询操作中用到,这里我借鉴的是论坛一个朋友的写法。把页码导航设计封装在一个专门的js中(pageNav.js),在前端的页面中要用到分页查询的时候就导入它即可。源代码都在本篇博文末尾的源码下载链接中。当然,你觉得不够喜欢你也可以设计你自己的前端分页查询页码显示的导航栏。
PS:本篇教程只作为引导,代码水平很菜,但是适合初学者学习借鉴。另外,js,css代码就不贴了,大家有需要可以点击此处下载源代码。
五、测试
至此,mybatis三剑客之mybatis pagehelper分页查询的教程到此结束,需要完整源代码的点击下载