MyBatis实现分页的方式

MyBatis实现分页的方式

1.SQL原生拼接

currIndexpageSize作为查询时参数在执行查询SQL时填充

xml文件

<select id="queryStudentsBySql" parameterType="map" resultMap="studentmapper">
        select * from student limit #{currIndex} , #{pageSize}
</select>

service

接口
List<Student> queryStudentsBySql(int currPage, int pageSize);
实现类
public List<Student> queryStudentsBySql(int currPage, int pageSize) {
        Map<String, Object> data = new HashedMap();
        data.put("currIndex", (currPage-1)*pageSize);
        data.put("pageSize", pageSize);
        return studentMapper.queryStudentsBySql(data);
}

2.借助MyBabtis提供的RowBounds进行分页查询

数据量小时,RowBounds不失为一种好办法。但是数据量大时,实现拦截器就很有必要了。

mybatis接口加入RowBounds参数

public List<UserBean> queryUsersByPage(String userName, RowBounds rowBounds);

RowBounds

public class RowBounds {
    //默认值为0~~Java最大整数
    public static final int NO_ROW_OFFSET = 0;
    public static final int NO_ROW_LIMIT = Integer.MAX_VALUE;
    public static final RowBounds DEFAULT = new RowBounds();
    //偏移量,即从第几行开始读取
    private final int offset;
    //限制,即每页显示记录数量
    private final int limit;
 
    public RowBounds() {
        this.offset = NO_ROW_OFFSET;
        this.limit = NO_ROW_LIMIT;
    }
    public RowBounds(int offset, int limit) {
        this.offset = offset;
        this.limit = limit;
    }
    public int getOffset() {
        return offset;
    }
    public int getLimit() {
        return limit;
    }
}

Service

@Service
public class OrderInfoService {
 
    @Resource
    private OrderInfoMapper orderInfoMapper;
 
    public List<OrderInfo> getOrderInfoList(int pageNow, int pageSize) {
        RowBounds rowBounds = new RowBounds(pageNow,pageSize);
        return orderInfoMapper.getOrderInfoList(rowBounds);
    }
}

Mapper

@Mapper
public interface OrderInfoMapper {
    List<OrderInfo> getOrderInfoList(RowBounds rowBounds);
}

3.自定义拦截器 Intercepter

自定义拦截器插件分页 需要自己定义一个类实现Interceptor接口,这个接口是Mybatis提供的。任何分页插件想要对Mybatis进行分页就必须实现Interceptor接口,包括后面PageHelper分页插件。

①、创建MyPageInterceptor

/**
 * @Intercepts 表示是一个拦截器
 * @Signature 拦截器的签名
 * type 拦截的类型 四大对象之一( Executor,ResultSetHandler,ParameterHandler,StatementHandler)
 * method 拦截的方法
 */
@Intercepts({@Signature(type=StatementHandler.class,method="prepare",args={Connection.class, Integer.class })})
public class MyPageInterceptor implements Interceptor {
 
    //当前页码
    private int currPage;
    //每页显示的条目数
    private int pageSize;
    //数据库类型
    private String dbType;
 
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("plugin is running...");
        //获取StatementHandler,默认是RoutingStatementHandler
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        //获取statementHandler包装类
        MetaObject MetaObjectHandler = SystemMetaObject.forObject(statementHandler);
 
        //分离代理对象链
        while (MetaObjectHandler.hasGetter("h")) {
            Object obj = MetaObjectHandler.getValue("h");
            MetaObjectHandler = SystemMetaObject.forObject(obj);
        }
 
        while (MetaObjectHandler.hasGetter("target")) {
            Object obj = MetaObjectHandler.getValue("target");
            MetaObjectHandler = SystemMetaObject.forObject(obj);
        }
 
        //获取连接对象
        //Connection connection = (Connection) invocation.getArgs()[0];
        //object.getValue("delegate");  获取StatementHandler的实现类
 
        //获取查询接口映射的相关信息
        MappedStatement mappedStatement = (MappedStatement) MetaObjectHandler.getValue("delegate.mappedStatement");
        String mapId = mappedStatement.getId();
 
        //statementHandler.getBoundSql().getParameterObject();
 
        //拦截以.ByPage结尾的请求,分页功能的统一实现
        if (mapId.matches(".+ByPage$")) {
            //获取进行数据库操作时管理参数的handler
            ParameterHandler parameterHandler = (ParameterHandler) MetaObjectHandler.getValue("delegate.parameterHandler");
            //获取请求时的参数
            Map<String, Object> paraObject = (Map<String, Object>) parameterHandler.getParameterObject();
            //也可以这样获取
            //paraObject = (Map<String, Object>) statementHandler.getBoundSql().getParameterObject();
 
            //参数名称和在service中设置到map中的名称一致
            currPage = (int) paraObject.get("currPage");
            pageSize = (int) paraObject.get("pageSize");
 
            String sql = (String) MetaObjectHandler.getValue("delegate.boundSql.sql");
            //也可以通过statementHandler直接获取
            //sql = statementHandler.getBoundSql().getSql();
 
            //构建分页功能的sql语句
            String limitSql;
            sql = sql.trim();
            limitSql = sql + " limit " + (currPage - 1) * pageSize + "," + pageSize;
 
            //将构建完成的分页sql语句赋值个体'delegate.boundSql.sql',偷天换日
            MetaObjectHandler.setValue("delegate.boundSql.sql", limitSql);
        }
        //调用原对象的方法,进入责任链的下一级
        return invocation.proceed();
    }
 
    //获取代理对象
    @Override
    public Object plugin(Object o) {
        //生成object对象的动态代理对象
        return Plugin.wrap(o, this);
    }
 
    //设置代理对象的参数
    @Override
    public void setProperties(Properties properties) {
        //如果项目中分页的pageSize是统一的,也可以在这里统一配置和获取,这样就不用每次请求都传递pageSize参数了。参数是在配置拦截器时配置的。
        String limit1 = properties.getProperty("limit", "10");
        this.pageSize = Integer.valueOf(limit1);
        this.dbType = properties.getProperty("dbType", "mysql");
    }
}

②、全局配置文件增加plugin设置(注意位置)

<!-- 配置自定义分页插件 -->
<plugins>  
    <plugin interceptor="com.thr.interceptor.MyPageInterceptor"></plugin>
 </plugins>

③、接口方法

//分页查询所有用户,通过原生自定义拦截器
List<User> selectAllUserByPage(Map map);

由于拦截器中设置了拦截以ByPage结尾的方法,所以方法一定要命名正确,

4. PageHelper插件

①、引入PageHelper依赖:

<!-- pagehelper分页插件 -->
<dependency>  
    <groupId>com.github.pagehelper</groupId>  
    <artifactId>pagehelper</artifactId>  
    <version>5.2.0</version></dependency>
</dependency>

②、全局配置文件增加plugin设置(注意位置)

<!-- 配置分页插件 -->
<plugins>  
    <!-- PageHelper5版本配置 -->  
    <plugin` `interceptor="com.github.pagehelper.PageInterceptor"/>
</plugins>

③、测试方法

//分页查询所有用户信息,通过PageHelper
@Test
public void selectAllUserByPageHelper(){  
    int currPage = 2;
    //当前页码  int` `pageSize = 3;
    //当前页记录数量  
    //表示获取第2页,3条内容,默认会查询总数count  
    PageHelper.startPage(currPage,pageSize);  
    List<User> userList = mapper.selectAllUserByPageHelper();  
    for(User user : userList) 
    {    System.out.println(user);  
    }
}
posted @ 2024-05-27 10:51  FlyHippo  阅读(114)  评论(0编辑  收藏  举报