Java使用MyBatis框架分页的5种方式
本文为大家分享了Java使用MyBatis框架分页的五种方式,供大家参考,具体内容如下
初始准备
1.创建分页对象类,方便模块间传值
//PageInfo.java
importlombok.Data;
@Data
publicclassPageInfo{
privateintpageNo;
privateintpageSize;
}
2.定义DAO层接口
importorg.apache.ibatis.session.RowBounds;
importorg.springframework.stereotype.Repository;
importjava.util.List;
@Repository
publicinterfaceUserMapper{
UserselectByUser(Useruser);
ListselectAll();
ListselectByPageInfo(PageInfoinfo);
ListselectByInterceptor(PageInfoinfo);
ListselectByRowBounds(RowBoundsrowBounds);
}
3.mapper中定义结果集合BaseResult
一、原始切分:最原始方法,不建议使用
1.mapper代码:查询所有数据
select*fromtb_user
2.业务层代码:利用List的subList()方法对数据进行切片
publicListfindByAll(PageInfoinfo){ List users=userMapper.selectAll(); returnusers.subList(info.getPageNo(),info.getPageSize()); }
3.控制层代码
@RequestMapping(value="/userlist_1",method=RequestMethod.GET)
@ResponseBody
publicResultfindUserBySubList(PageInfoinfo){
Listusers=userService.findByAll(info);
if(users.size()==0){
returnResultGenerator.genFailResult("未查找到用户");
}
returnResultGenerator.genSuccessResult(users);
}
二、LIMIT关键字
1.mapper代码:利用limit关键字实现分页
select*fromtb_userlimit#{pageNo},#{pageSize}
2.业务层直接调用
publicListfindByPageInfo(PageInfoinfo){ returnuserMapper.selectByPageInfo(info); }
3.控制层直接调用
三、RowBounds实现分页
1.在DAO层定义好所要传输的分页信息,类型为RowBounds
2.mapper层:查询所有数据
3.业务层:将PageInfo信息封装成RowBounds,调用DAO层方法
publicListfindByRowBounds(PageInfoinfo){ returnuserMapper.selectByRowBounds(newRowBounds(info.getPageNo(),info.getPageSize())); }
4.控制层直接调用
四、MyBatis的Interceptor实现:实现复杂,需要明白MyBatis的实现
1.创建Interceptor
importorg.apache.ibatis.executor.parameter.ParameterHandler;
importorg.apache.ibatis.executor.statement.StatementHandler;
importorg.apache.ibatis.mapping.MappedStatement;
importorg.apache.ibatis.plugin.*;
importorg.apache.ibatis.reflection.MetaObject;
importorg.apache.ibatis.reflection.SystemMetaObject;
importjava.sql.Connection;
importjava.util.Properties;
/**
*利用MyBatis拦截器进行分页
*
*@Intercepts说明是一个拦截器
*@Signature拦截器的签名
*type拦截的类型四大对象之一(Executor,ResultSetHandler,ParameterHandler,StatementHandler)
*method拦截的方法
*args参数,高版本需要加个Integer.class参数,不然会报错
*
*/
@Intercepts({@Signature(type=StatementHandler.class,method="prepare",args={Connection.class,Integer.class})})
publicclassDefinedPageInterceptorimplementsInterceptor{
@Override
publicObjectintercept(Invocationinvocation)throwsThrowable{
//获取StatementHandler,默认的是RoutingStatementHandler
StatementHandlerstatementHandler=(StatementHandler)invocation.getTarget();
//获取StatementHandler的包装类
MetaObjectmetaObject=SystemMetaObject.forObject(statementHandler);
//分隔代理对象
while(metaObject.hasGetter("h")){
Objectobj=metaObject.getValue("h");
metaObject=SystemMetaObject.forObject(obj);
}
while(metaObject.hasGetter("target")){
Objectobj=metaObject.getValue("target");
metaObject=SystemMetaObject.forObject(obj);
}
//获取查看接口映射的相关信息
MappedStatementmappedStatement=(MappedStatement)metaObject.getValue("delegate.mappedStatement");
StringmapId=mappedStatement.getId();
//拦截以ByInterceptor结尾的请求,统一实现分页
if(mapId.matches(".+ByInterceptor$")){
System.out.println("LOG:已触发分页拦截器");
//获取进行数据库操作时管理参数的Handler
ParameterHandlerparameterHandler=(ParameterHandler)metaObject.getValue("delegate.parameterHandler");
//获取请求时的参数
PageInfoinfo=(PageInfo)parameterHandler.getParameterObject();
//获取原始SQL语句
StringoriginalSql=(String)metaObject.getValue("delegate.boundSql.sql");
//构建分页功能的SQL语句
Stringsql=originalSql.trim()+"limit"+info.getPageNo()+","+info.getPageSize();
metaObject.setValue("delegate.boundSql.sql",sql);
}
//调用原对象方法,进入责任链下一级
returninvocation.proceed();
}
@Override
publicObjectplugin(Objecttarget){
//生成Object对象的动态代理对象
returnPlugin.wrap(target,this);
}
@Override
publicvoidsetProperties(Propertiesproperties){
//如果分页每页数量是统一的,可以在这里进行统一配置,也就无需再传入PageInfo信息了
}
}
2.将Interceptor添加至MyBatisConfig中,这里采用JavaConfig的方式
@Bean
publicSqlSessionFactoryBeansqlSession(){
SqlSessionFactoryBeansqlSession=newSqlSessionFactoryBean();
sqlSession.setDataSource(dataSource());
try{
Resource[]resources=newPathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml");
sqlSession.setMapperLocations(resources);
//配置自定义的Interceptro作为MyBatis的Interceptor,完成分页操作
DefinedPageInterceptordefinedPageInterceptor=newDefinedPageInterceptor();
sqlSession.setPlugins(newInterceptor[]{definedPageInterceptor});
returnsqlSession;
}catch(IOExceptione){
e.printStackTrace();
}
returnnull;
}
3.DAO层接口方法名需要和代码中自定义的".+ByInterceptor$"正则表达式相匹配,mapper的书写依然是查询所有数据
select*fromtb_user
4.业务层直接调用
5.控制层直接调用
五、开源项目PageHelper实现:本质还是自己封装了个Interceptor
1.引入PageHelper的jar包
com.github.pagehelper pagehelper 5.1.10
2.配置PageInterceptor
publicPageInterceptorinitPageInterceptor(){
PageInterceptorpageInterceptor=newPageInterceptor();
Propertiesproperties=newProperties();
//设置数据库类型
properties.setProperty("helperDialect","mysql");
//该参数默认为false
//设置为true时,会将RowBounds第一个参数offset当成pageNum页码使用
//和startPage中的pageNum效果一样
properties.setProperty("offsetAsPageNum","true");
//该参数默认为false
//设置为true时,使用RowBounds分页会进行count查询
properties.setProperty("rowBoundsWithCount","true");
pageInterceptor.setProperties(properties);
returnpageInterceptor;
}
@Bean
publicSqlSessionFactoryBeansqlSession(){
SqlSessionFactoryBeansqlSession=newSqlSessionFactoryBean();
sqlSession.setDataSource(dataSource());
try{
Resource[]resources=newPathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml");
sqlSession.setMapperLocations(resources);
//配置PageHelper作为MyBatis的Interceptor,完成分页操作
PageInterceptorpageInterceptor=this.initPageInterceptor();
//配置自定义的Interceptro作为MyBatis的Interceptor,完成分页操作
DefinedPageInterceptordefinedPageInterceptor=newDefinedPageInterceptor();
sqlSession.setPlugins(newInterceptor[]{pageInterceptor,definedPageInterceptor});
returnsqlSession;
}catch(IOExceptione){
e.printStackTrace();
}
returnnull;
}
3.mapper依然是查询所有数据
4.为DAO层再封装一次方法
@Repository
publicclassPageHelperHandler{
@Autowired
privateSqlSessionFactorysqlSessionFactory;
publicListfindByPageHelper(PageInfoinfo){
SqlSessionsession=sqlSessionFactory.openSession();
PageHelper.startPage(info.getPageNo(),info.getPageSize());
//写到要使用到的类名和方法名
Listusers=session.selectList("cn.edu.yau.mapper.UserMapper.selectAll");
returnusers;
}
}
6.业务层直接调用Handler
7.控制层直接调用
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。