重点:
分页插件要能在项目中使用,能使用SpringSecurity在项目中实现用户拦截配置
select * from
(
select rownum rn,p.* from product p
) rp
where
rp.rn between 1 and 3;
--把rn作为分页的条件
select * from
(
--在排序结果中再次查询,把rownum作为结果集的一列
select rownum rn,p.* from
(
--查询同时实现排序
select * from product order by productprice desc
) p
)
where
rn between 1 and 3;
MySQL中的分页相对而言比较简单,直接使用limit实现分页即可。
select * from product order by productprice desc limit 0,10
从上面2个分页语句来看,针对不同数据库的分页,都需要2个参数,分别是第几页和每页显示多少条,也就是用户每次进行分页的时候,都应该讲第几页和每页显示多少条数据的2个参数传入到后台。
分页效果如下:
通过上面的图片,我们可以看到,每次都有对应的分页信息需要现实,我们可以讲对应的分页信息封装起来,封装代码如下:
public class PageBean<T> {
// 当前页,手动添加的默认值是1
private int pageCode = 1;
// 总页数
// private int totalPage;
// 总记录数
private int totalCount;
// 每页显示的记录条数,每页显示5条
private int pageSize = 5;
// 每页显示的数据
private List<T> beanList;
public int getPageCode() {
return pageCode;
}
public void setPageCode(int pageCode) {
this.pageCode = pageCode;
}
/**
* 调用getTotalPage() 获取到总页数
* JavaBean的属性规定:totalPage是JavaBean是属性 ${pageBean.totalPage}
* @return
*/
public int getTotalPage() {
// 计算
int totalPage = totalCount / pageSize;
// 说明整除
if(totalCount % pageSize == 0){
return totalPage;
}else{
return totalPage + 1;
}
}
/*public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}*/
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public List<T> getBeanList() {
return beanList;
}
public void setBeanList(List<T> beanList) {
this.beanList = beanList;
}
}
根据上面的分析,前台需要向后台传递2个参数,分别是每页显示多少条(size)和当前页(page),一般我们在查询列表页的时候,第一次请求不会加分页参数,所以应该要给他们默认参数,首次请求列表页,我们可以让size=5,page=1,这也符合工作中的现实要求。
修改ProductController,将列表查询的方法做如下改造:
/***
* 商品列表查询
* @param model
* @return
*/
@RequestMapping(value = "/list")
public String list(@RequestParam(value = "page",required = false,defaultValue = "1")int page,
@RequestParam(value = "size",required = false,defaultValue = "5")int size,
Model model){
//集合查询
PageBean<Product> pageInfo = productService.pageList(page,size);
//将数据存入到Model中
model.addAttribute("pageInfo",pageInfo);
return "product-list";
}
修改ProductService接口
//接口
PageBean<Product> pageList(int page, int size);
修改ProductServiceImpl实现类
/***
* 产品分页查询
* @param page
* @param size
* @return
*/
@Override
public PageBean<Product> pageList(int page, int size) {
//创建一个PageBean
PageBean<Product> pageInfo = new PageBean<Product>();
//查询总数
int total = productDao.findCount();
pageInfo.setTotalCount(total);
/***
* 查询列表记录
*/
List<Product> products = productDao.pageList((page-1)*size,page*size);
pageInfo.setBeanList(products);
return pageInfo;
}
修改ProductDao,由于我们之前传递的入参是一个JavaBean对象,所以可以直接用#{属性名}来取对应SQL语句占位符的参数,但是如果入参是多个基本数据类型或者多个String类型,我们就无法像之前那么去取,我们可以使用一个注解来实现参数别名的标记@Param(value=“别名”),用@Param之后,SQL语句就可以直接取@Param(value=“name”)中的name了。
/***
* 分页查询
* 我们这里采用了不使用排序的分页方式
* @return
* @param start
* @param end
*/
@Select("select * from product limit #{start} , #{end}")
List<Product> pageList(@Param(value = "start")int start, @Param(value = "end")int end);
将c:forEach中的items所取的迭代对象换成pageInfo.beanList,其他不变。
//...略
分页数据填充
PageHelper是国内非常优秀的一款开源的mybatis分页插件,它支持基本主流与常用的数据库,例如mysql、oracle、mariaDB、DB2、SQLite、Hsqldb等。
网址:https://pagehelper.github.io/
本项目在 github 的项目地址:https://github.com/pagehelper/Mybatis-PageHelper
本项目在 gitosc 的项目地址:http://git.oschina.net/free/Mybatis_PageHelper
分页插件学习文档:https://pagehelper.github.io/docs/howtouse/
这个案例用到了AdminLTE项目,下面是我的中文-jsp版本
分页插件中文-jsp版本地址:https://github.com/MainPoser/AdminLTE-jsp-chinese
引入分页插件有下面2种方式,推荐使用 Maven 方式。
你可以从下面的地址中下载最新版本的 jar 包
https://oss.sonatype.org/content/repositories/releases/com/github/pagehelper/pagehelper/
http://repo1.maven.org/maven2/com/github/pagehelper/pagehelper/
由于使用了sql 解析工具,你还需要下载 jsqlparser.jar:
http://repo1.maven.org/maven2/com/github/jsqlparser/jsqlparser/0.9.5/
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>最新版本version>
dependency>
特别注意,新版拦截器是 com.github.pagehelper.PageInterceptor。 com.github.pagehelper.PageHelper 现在是一个特殊的 dialect 实现类,是分页插件的默认实现类,提供了和以前相同的用法。
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="param1" value="value1"/>
plugin>
plugins>
使用 spring 的属性配置方式,可以使用 plugins 属性像下面这样配置:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<value>
params=value1
helperDialect=mysql
value>
property>
bean>
array>
property>
bean>
特别注意:使用 SqlServer2012 数据库时,需要手动指定为 sqlserver2012,否则会使用 SqlServer2005 的方式进行分页。
你也可以实现 AbstractHelperDialect,然后配置该属性为实现类的全限定名称即可使用自定义的实现方法。
PageHelper的基本使用有6种,大家可以查看文档,最常用的有两种
List<Country> list = sqlSession.selectList("x.y.selectIf", null, new RowBounds(1, 10));
使用这种调用方式时,你可以使用RowBounds参数进行分页,这种方式侵入性最小,我们可以看到,通过RowBounds方式调用只是使用了这个参数,并没有增加其他任何内容。
分页插件检测到使用了RowBounds参数时,就会对该查询进行物理分页。
关于这种方式的调用,有两个特殊的参数是针对 RowBounds 的,你可以参看上面的分页插件参数介绍
注:不只有命名空间方式可以用RowBounds,使用接口的时候也可以增加RowBounds参数,例如:
//这种情况下也会进行物理分页查询
List<Country> selectAll(RowBounds rowBounds);
注意: 由于默认情况下的 RowBounds 无法获取查询总数,分页插件提供了一个继承自 RowBounds 的 PageRowBounds,这个对象中增加了 total 属性,执行分页查询后,可以从该属性得到查询总数。
在你需要进行分页的 MyBatis 查询方法前调用PageHelper.startPage 静态方法即可,紧跟在这个方法后的第一个MyBatis 查询方法会被进行分页。
//获取第1页,10条内容,默认查询总数count
PageHelper.startPage(1, 10);
//紧跟着的第一个select方法会被分页
List<Country> list = countryMapper.selectIf();
以下是PageHelper自带的分页对象,基本能满足我们平时工作的分页需求,等会我们就直接使用它。
public class PageInfo<T> implements Serializable {
private static final long serialVersionUID = 1L;
//当前页
private int pageNum;
//每页的数量
private int pageSize;
//当前页的数量
private int size;
//由于startRow和endRow不常用,这里说个具体的用法
//可以在页面中"显示startRow到endRow 共size条数据"
//当前页面第一个元素在数据库中的行号
private int startRow;
//当前页面最后一个元素在数据库中的行号
private int endRow;
//总记录数
private long total;
//总页数
private int pages;
//结果集
private List<T> list;
//前一页
private int prePage;
//下一页
private int nextPage;
//是否为第一页
private boolean isFirstPage = false;
//是否为最后一页
private boolean isLastPage = false;
//是否有前一页
private boolean hasPreviousPage = false;
//是否有下一页
private boolean hasNextPage = false;
//导航页码数
private int navigatePages;
//所有导航页号
private int[] navigatepageNums;
//导航条上的第一页
private int navigateFirstPage;
//导航条上的最后一页
private int navigateLastPage;
//...略
}
使用5.1.2的版本,分别在父工程和dao工程中导入以上包,父工程做版本的管理,子工程直接使用。
修改ssm-parent的pom.xml,在properties中加入版本
<properties>
//....略
//分页版本
<pagehelper.version>5.1.2pagehelper.version>
properties>
修改ssm-parent的pom.xml,在dependencies中加入如下依赖
<dependencies>
//...略
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>${pagehelper.version}version>
dependency>
dependencies>
修改ssm-dao的pom.xml,在dependencies中加入如下依赖
<dependencies>
//...略
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
dependency>
dependencies>
在ssm-dao工程中,修改spring-mybatis.xml,找到SqlSessionFactoryBean结点的配置,修改如下:
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="plugins">
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<props>
<prop key="helperDialect">mysqlprop>
<prop key="reasonable">trueprop>
props>
property>
bean>
property>
bean>
将返回类型修改成PageInfo,创建一个方法pageHelperList。
/***
* 商品列表查询
* @param model
* @return
*/
@RequestMapping(value = "/list")
public String list(@RequestParam(value = "page",required = false,defaultValue = "1")int page,
@RequestParam(value = "size",required = false,defaultValue = "5")int size,
Model model){
//集合查询
PageInfo<Product> pageInfo = productService.pageHelperList(page,size);
//将数据存入到Model中
model.addAttribute("pageInfo",pageInfo);
return "product-list";
}
接口:
/***
* 列表查询
* @param page
* @param size
* @return
*/
PageInfo<Product> pageHelperList(Integer page,Integer size);
实现类:
@Override
public PageInfo<Product> pageHelperList(Integer page, Integer size) {
//1)静态分页
PageHelper.startPage(page,size);
//2)集合查询
List<Product> products = productMapper.list();
//3)返回PageInfo:包含数据结果集+分页信息
return new PageInfo<Product>(products);
}
/****
* 查询
* @return
*/
@Select("select * from product")
List<Product> list();
首先要修改JSP中数据输出
//...略
找到分页参数,做一定修改,如下: