欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java使用MyBatis框架分页的5种方式

程序员文章站 2023-11-29 18:55:10
本文为大家分享了java使用mybatis框架分页的五种方式,供大家参考,具体内容如下 初始准备 1.创建分页对象类,方便模块间传值 //pageinfo.j...

本文为大家分享了java使用mybatis框架分页的五种方式,供大家参考,具体内容如下

初始准备

1.创建分页对象类,方便模块间传值

//pageinfo.java
import lombok.data;

@data
public class pageinfo {

 private int pageno;

 private int pagesize;

}

2.定义dao层接口

import org.apache.ibatis.session.rowbounds;
import org.springframework.stereotype.repository;

import java.util.list;

@repository
public interface usermapper {

 user selectbyuser(user user);
 list<user> selectall();
 list<user> selectbypageinfo(pageinfo info);
 list<user> selectbyinterceptor(pageinfo info);

 list<user> selectbyrowbounds(rowbounds rowbounds);

}

3.mapper中定义结果集合baseresult

<resultmap id="baseresult" type="cn.edu.yau.pojo.user">
  <id property="id" column="id" jdbctype="integer"></id>
  <result property="username" column="username" jdbctype="varchar"></result>
  <result property="password" column="password" jdbctype="varchar"></result>
 </resultmap>

一、原始切分:最原始方法,不建议使用

1.mapper代码:查询所有数据

<select id="selectall" resultmap="baseresult">
 select * from tb_user
</select>

2.业务层代码:利用list的sublist()方法对数据进行切片

public list<user> findbyall(pageinfo info) {
  list<user> users = usermapper.selectall();
  return users.sublist(info.getpageno(), info.getpagesize());
 }

3.控制层代码

@requestmapping(value = "/userlist_1", method = requestmethod.get)
@responsebody
 public result finduserbysublist(pageinfo info) {
  list<user> users = userservice.findbyall(info);
  if(users.size() == 0) {
   return resultgenerator.genfailresult("未查找到用户");
  }
  return resultgenerator.gensuccessresult(users);
 }

二、limit关键字

1.mapper代码:利用limit关键字实现分页

<select id="selectbypageinfo" resultmap="baseresult">
  select * from tb_user limit #{pageno}, #{pagesize}
</select>

2.业务层直接调用

public list<user> findbypageinfo(pageinfo info) {
  return usermapper.selectbypageinfo(info);
 }

3.控制层直接调用

三、rowbounds实现分页

1.在dao层定义好所要传输的分页信息,类型为rowbounds

2.mapper层:查询所有数据

3.业务层:将pageinfo信息封装成rowbounds,调用dao层方法

public list<user> findbyrowbounds(pageinfo info) {
  return usermapper.selectbyrowbounds(new rowbounds(info.getpageno(), info.getpagesize()));
 }

4.控制层直接调用

四、mybatis的interceptor实现:实现复杂,需要明白mybatis的实现

1.创建interceptor

import org.apache.ibatis.executor.parameter.parameterhandler;
import org.apache.ibatis.executor.statement.statementhandler;
import org.apache.ibatis.mapping.mappedstatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.metaobject;
import org.apache.ibatis.reflection.systemmetaobject;

import java.sql.connection;
import java.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})})
public class definedpageinterceptor implements interceptor {

 @override
 public object intercept(invocation invocation) throws throwable {
  //获取statementhandler,默认的是routingstatementhandler
  statementhandler statementhandler = (statementhandler) invocation.gettarget();
  //获取statementhandler的包装类
  metaobject metaobject = systemmetaobject.forobject(statementhandler);
  //分隔代理对象
  while (metaobject.hasgetter("h")) {
   object obj = metaobject.getvalue("h");
   metaobject = systemmetaobject.forobject(obj);
  }
  while (metaobject.hasgetter("target")) {
   object obj = metaobject.getvalue("target");
   metaobject = systemmetaobject.forobject(obj);
  }
  //获取查看接口映射的相关信息
  mappedstatement mappedstatement = (mappedstatement) metaobject.getvalue("delegate.mappedstatement");
  string mapid = mappedstatement.getid();
  //拦截以byinterceptor结尾的请求,统一实现分页
  if (mapid.matches(".+byinterceptor$")) {
   system.out.println("log:已触发分页拦截器");
   //获取进行数据库操作时管理参数的handler
   parameterhandler parameterhandler = (parameterhandler) metaobject.getvalue("delegate.parameterhandler");
   //获取请求时的参数
   pageinfo info = (pageinfo) parameterhandler.getparameterobject();
   //获取原始sql语句
   string originalsql = (string) metaobject.getvalue("delegate.boundsql.sql");
   //构建分页功能的sql语句
   string sql = originalsql.trim() + " limit " + info.getpageno() + ", " + info.getpagesize();
   metaobject.setvalue("delegate.boundsql.sql", sql);
  }
  //调用原对象方法,进入责任链下一级
  return invocation.proceed();
 }

 @override
 public object plugin(object target) {
  //生成object对象的动态代理对象
  return plugin.wrap(target, this);
 }

 @override
 public void setproperties(properties properties) {
  //如果分页每页数量是统一的,可以在这里进行统一配置,也就无需再传入pageinfo信息了
 }
}

2.将interceptor添加至mybatisconfig中,这里采用javaconfig的方式

@bean
 public sqlsessionfactorybean sqlsession() {
  sqlsessionfactorybean sqlsession = new sqlsessionfactorybean();
  sqlsession.setdatasource(datasource());
  try {
   resource[] resources = new pathmatchingresourcepatternresolver().getresources("classpath:mapper/*.xml");
   sqlsession.setmapperlocations(resources);
   //配置自定义的interceptro作为mybatis的interceptor,完成分页操作
   definedpageinterceptor definedpageinterceptor = new definedpageinterceptor();
   sqlsession.setplugins(new interceptor[]{definedpageinterceptor});
   return sqlsession;
  } catch (ioexception e) {
   e.printstacktrace();
  }
  return null;
 }

3.dao层接口方法名需要和代码中自定义的".+byinterceptor$"正则表达式相匹配,mapper的书写依然是查询所有数据

<select id="selectbyinterceptor" resultmap="baseresult">
  select * from tb_user
</select>

4.业务层直接调用

5.控制层直接调用

五、开源项目pagehelper实现:本质还是自己封装了个interceptor

1.引入pagehelper的jar包

<dependency>
  <groupid>com.github.pagehelper</groupid>
  <artifactid>pagehelper</artifactid>
  <version>5.1.10</version>
</dependency>

2.配置pageinterceptor

public pageinterceptor initpageinterceptor(){
  pageinterceptor pageinterceptor = new pageinterceptor();
  properties properties = new properties();
  //设置数据库类型
  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);
  return pageinterceptor;
 }

 @bean
 public sqlsessionfactorybean sqlsession() {
  sqlsessionfactorybean sqlsession = new sqlsessionfactorybean();
  sqlsession.setdatasource(datasource());
  try {
   resource[] resources = new pathmatchingresourcepatternresolver().getresources("classpath:mapper/*.xml");
   sqlsession.setmapperlocations(resources);
   //配置pagehelper作为mybatis的interceptor,完成分页操作
   pageinterceptor pageinterceptor = this.initpageinterceptor();
   //配置自定义的interceptro作为mybatis的interceptor,完成分页操作
   definedpageinterceptor definedpageinterceptor = new definedpageinterceptor();
   sqlsession.setplugins(new interceptor[]{pageinterceptor, definedpageinterceptor});
   return sqlsession;
  } catch (ioexception e) {
   e.printstacktrace();
  }
  return null;
 }

3.mapper依然是查询所有数据

4.为dao层再封装一次方法

@repository
public class pagehelperhandler {

 @autowired
 private sqlsessionfactory sqlsessionfactory;

 public list<user> findbypagehelper(pageinfo info) {
  sqlsession session = sqlsessionfactory.opensession();
  pagehelper.startpage(info.getpageno(), info.getpagesize());
  //写到要使用到的类名和方法名
  list<user> users = session.selectlist("cn.edu.yau.mapper.usermapper.selectall");
  return users;
 }

}

6.业务层直接调用handler

7.控制层直接调用

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。