MyBatis实现分页的方式
MyBatis实现分页的方式
1.SQL原生拼接
将currIndex
,pageSize
作为查询时参数在执行查询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);
}
}