MyBatis分页插件的使用(1) | 您所在的位置:网站首页 › pagehelper支持国产数据库吗 › MyBatis分页插件的使用(1) |
前言
`在mysql中,分页的sql是使用limit来做的。但是一旦model多了起来,那么就很难维护了。而使用分页插件PageHelper正好可以解决这一问题。 分页插件PageHelper是通过mybatis的拦截器实现分页功能的,拦截sql查询请求,添加分页语句,最终实现分页查询功能。 一、分页插件PageHelper支持的数据库类型?Oracle,MySql,MariaDB,SQLite等 二、分页插件PageHelper的原理一次请求就是一个线程,PageHelper.startPage(page,size)中携带分页参数。分页参数会设置在ThreadLocal中。PageHelper会在mybatis执行sql前进行拦截,从ThreadLocal中取出分页参数,修改当前执行的sql语句,添加分页sql,最后执行了添加了分页的sql语句,实现分页查询 1.在springboot的应用程序中引入依赖(pom.xml) PageInterceptor.java: package cn.wangh.page; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.Map; import java.util.Properties; import org.apache.ibatis.executor.parameter.ParameterHandler; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.plugin.Intercepts; import org.apache.ibatis.plugin.Invocation; import org.apache.ibatis.plugin.Plugin; import org.apache.ibatis.plugin.Signature; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.SystemMetaObject; import cn.wangh.model.Page; /** 分页拦截器 */ @Intercepts({@Signature(type=StatementHandler.class,method=“prepare”,args={Connection.class})}) public class PageInterceptor implements Interceptor { private String databaseType;// 数据库类型,不同的数据库有不同的分页方法 @Override public Object intercept(Invocation invocation) throws Throwable { StatementHandler statementHandler = (StatementHandler)invocation.getTarget(); MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY); MappedStatement mappedStatement = (MappedStatement)metaObject.getValue(“delegate.mappedStatement”); // 配置文件中SQL语句的ID String id = mappedStatement.getId(); if(id.matches(".+ByPage$")) { BoundSql boundSql = statementHandler.getBoundSql(); // 原始的SQL语句 String sql = boundSql.getSql(); // 查询总条数的SQL语句 String countSql = “select count(*) from (” + sql + “) table_count”; Connection connection = (Connection)invocation.getArgs()[0]; PreparedStatement countStatement = connection.prepareStatement(countSql); // 通过反射获取到当前ParameterHandler对象的delegate属性 ParameterHandler parameterHandler = (ParameterHandler)metaObject.getValue(“delegate.parameterHandler”); parameterHandler.setParameters(countStatement); ResultSet rs = countStatement.executeQuery(); Map parameter = (Map)boundSql.getParameterObject(); Page page = (Page)parameter.get("page"); if(rs.next()) { page.setTotalNumber(rs.getInt(1)); } // 改造后带分页查询的SQL语句// String pageSql = sql + " limit " + page.getDbIndex() + “,” + page.getDbNumber(); String pageSql = getPageSql(page, sql); metaObject.setValue(“delegate.boundSql.sql”, pageSql); } return invocation.proceed(); } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { this.databaseType = properties.getProperty("databaseType"); } /** * 根据page对象获取对应的分页查询Sql语句,这里只做了两种数据库类型,Mysql和Oracle 其它的数据库都没有进行分页 */ private String getPageSql(Page page, String sql) { final StringBuffer sqlBuffer = new StringBuffer(sql); if ("mysql".equalsIgnoreCase(databaseType)) { return getMysqlPageSql(page, sqlBuffer); } else if ("oracle".equalsIgnoreCase(databaseType)) { return getOraclePageSql(page, sqlBuffer); } return sqlBuffer.toString(); } /** * 获取Oracle数据库的分页查询语句 */ private String getOraclePageSql(Page page, StringBuffer sqlBuffer) { // 计算第一条记录的位置,Oracle分页是通过rownum进行的,而rownum是从1开始的 final int offset = (page.getCurrentPage() - 1) * page.getDbNumber() + 1; sqlBuffer.insert(0, "select u.*, rownum r from (").append(") u where rownum < ") .append(offset + page.getDbNumber()); sqlBuffer.insert(0, "select * from (").append(") where r >= ").append(offset); // 上面的Sql语句拼接之后大概是这个样子: // select * from (select u.*, rownum r from (select * from t_user) u // where rownum < 31) where r >= 16 return sqlBuffer.toString(); } /** * 获取Mysql数据库的分页查询语句 */ private String getMysqlPageSql(Page page, StringBuffer sqlBuffer) { // 计算第一条记录的位置,Mysql中记录的位置是从0开始的。 sqlBuffer.append(" limit ").append(page.getDbIndex()).append(",").append(page.getDbNumber()); return sqlBuffer.toString(); }} |
CopyRight 2018-2019 实验室设备网 版权所有 |