分页查询
需求:查询所有数据 方法1:采用Map传递参数查询
<select id="selectByMap" parameterType="map" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from t_users where 1=1
<if test="(rowsPerPage!=null) and (rowsPerPage > 0)">
limit
<if test="begin!=null">
${begin},
</if>
${rowsPerPage}
</if>
</select>
<select id="countByMap" parameterType="map" resultType="int">
select count(id) from t_users
</select>
修改映射接口
public interface UserMapper{
List<UserBean> selectByMap(Map<String,Object> map);
int countByMap(Map<String,Object> map);
}
业务实现
public class UserServImpl implmenets IUserServ{
public List<UserBean> getByPage(PageBean pages){
List<UserBean> res=new ArrayList<>();
Map<String,Object> map=new HashMap<>();
UserMapper
userMapper=MyBatisSessionFactory.getMapper(UserMapper.class);
if(pages!=null && pages.getRowsPerPage()>0){
if(pages.getPageNum()<1)
pages.setPageNum(1);
if(pages.getMaxPage()<1){
int rowsNum=userMapper.countByMap(map);
if(rowsNum<1)
return res;
int maxPage=(rowsNum1+pages.getRowsPerPage())/pages.getRowsPerPage();
pages.setRowsNum(rowsNum);
pages.setMaxPage(maxPage);
}
if(pages.getPageNum()>pages.getMaxPage())
pages.setPageNum(pages.getMaxPage());
int begin=(pages.getPageNum()-1)*pages.getRowsPerPage();
map.put("begin",begin);
map.put("rowsPerPage",pages.getRowsPerPage());
}
res.addAll(userMapper.selectByMap(map));
return res;
}
}
方法2:使用MyBatis提供的RowBounds 软分页 没有自行拼接limit语句
<select id="selectAll" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from t_users where 1=1
</select>
需要在声明的Mapper接口中添加一个额外的参数
List<User> selectAll(RowBounds rowBounds);
注意这里的声明的方法和xml中的配置不一致,会多一个参数rowbounds
UserMapper userMapper= MybatisSessionFactory.getMapper(UserMapper.class);
List<User> userList=userMapper.selectAll(new RowBounds(0,3));//参数1为起始行
好,参数2为每页行数
for (User user : userList) {
System.out.println(user);
}
方法3:PageHelper PageHelper是一款好用的开源免费的Mybatis第三方物理分页插件
1、添加依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
2、分页插件配置
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"> 注意版
本的问题
<!--配置数据库方言-->
<property name="helpDialect" value="mysql"/>
<!--要求进行分页参数的合理化处理-->
<property name="reasonable" value="true"/>
</plugin>
</plugins> 注意版本的问题
3、编码调用
UserMapper userMapper= MybatisSessionFactory.getMapper(UserMapper.class);
//设置分页相关参数,参数1为查询的页码值,参数2为每页行数
PageHelper.startPage(-200,3);
List<User> userList=userMapper.selectAll(); //紧邻的查询语句中自动添加了分页处理
4、获取分页相关数据
UserMapper userMapper= MybatisSessionFactory.getMapper(UserMapper.class);
PageHelper.startPage(-200,3);
List<User> userList=userMapper.selectAll();
userList.forEach(System.out::println);
Page<User> pageInfo=(Page)userList;
System.out.println("当前页码值:"+pageInfo.getPageNum());
System.out.println("最大页码值:"+pageInfo.getPages());
System.out.println("总行数:"+pageInfo.getTotal());
System.out.println("每页行数:"+pageInfo.getPageSize());
5、如何需要进行排序
//设置分页的相关参数,参数1为页码值,参数2为每页行数,参数3为排序处理,也就是order by子句
后面的内容
Page<Student> info=PageHelper.startPage(1,3,"id desc,name asc");
实现分页的原理–plugin的开发
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执 行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。 举例:select * from student,拦截sql后重写为:select t.* from (select * from student)t limit 0, 10 使用方言和MyBatis的拦截器来实现分页 1:配置插件
<plugins>
<plugin interceptor="com.yan.StatmentHandlerInterceptor"/>
</plugins>
2:写拦截器 Mybatis支持对Executor、StatementHandler、PameterHandler和ResultSetHandler 接口进行拦截, 也就是说会对这4种对象进行代理。所谓的PageHelper分页工具实际上就是自定义拦截器
@Intercepts({//通过注解配置拦截目标,也就是定义什么时候进行拦截处理,因为拦截接口只有
一个
@Signature(type = StatementHandler.class, //拦截StatementHandler对象中的
方法
method = "prepare", //拦截prepare这个方法
args = { Connection.class, Integer.class }) })//对应方法的参数
public class StatmentHandlerInterceptor implements Interceptor {
//具体的拦截处理逻辑
public Object intercept(Invocation invocation) throws Throwable {
System.out.println("intercept");
if (invocation.getTarget() instanceof StatementHandler) {//获取拦截
目标对象的类型
StatementHandler sh = (StatementHandler)
invocation.getTarget();//获取拦截目标对象
BoundSql bs = sh.getBoundSql();//获取StatementHandler中包含的SQL
对象
System.out.println(bs.getSql());
//如果需要修改bs中所存放的SQL语句,则必须通过反向映射实现
Class clz = bs.getClass();
Field field = clz.getDeclaredField("sql");
field.setAccessible(true);
field.set(bs, bs.getSql()+"修改的地方");
}
return invocation.proceed(); //继续向后执行,拦截器还是责任链模式,类似过
滤器,执行过程executor--statementhandler--parameterhandler--Typehander---
preparedStatement---ResultSethandler---statementhandler---executor
}
public Object plugin(Object arg0) { //用于实现将当前拦截器对象通过plugin方
式添加到MyBatis中
System.out.println("plugin");
return Plugin.wrap(arg0, this);
}
//接收在配置文件中的配置参数
public void setProperties(Properties properties) {
System.out.println(properties);
/*
<plugin interceptor="com.yan.interceptor.MyInterceptor">
<property name="name" value="tttt"/>
</plugin>
*/
}
}
样例:统计SQL语句的执行时间
//具体的拦截处理逻辑
public Object intercept(Invocation invocation) throws Throwable {
long start=System.currentTimeMillis();
String sql=null;
if (invocation.getTarget() instanceof StatementHandler) { //获取拦截目标
对象的类型
StatementHandler sh = (StatementHandler)
invocation.getTarget();获取拦截目标对象
BoundSql bs = sh.getBoundSql();//获取StatementHandler中包含的SQL对象
sql=bs.getSql();
//如果需要修改bs中所存放的SQL语句,则必须通过反向映射实现
}
Object res= invocation.proceed(); //继续向后执行
long end=System.currentTimeMillis();
System.out.println(sql+"执行时间为:"+(end-start)+"ms");
return res;
}