后台查询数据的时如果数据量较多需要对数据进行分页处理,Mybatis有多种方法能够实现数据分页, 最简单的就是利用原生的sql关键字limit
来实现分页,也可以利用interceptor
来拼接sql实现分页功能,还可以利用PageHelper
开源框架来实现分页。
首先创建一个Mybatis工程 【Spring】Spring整合Mybatis案例
工程结构如下:
public class Pager<T> {
private int page;//分页起始页
private int size;//每页记录数
private List<T> data;//返回的记录集合
private long total;//总记录条数
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public List<T> getData() {
return data;
}
public void setData(List<T> data) {
this.data = data;
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
@Override
public String toString() {
return "Pager{" +
"page=" + page +
", size=" + size +
", data=" + data +
", total=" + total +
'}';
}
}
UserMapper
中添加两个方法
@Repository("userMapper")
@Mapper
public interface UserMapper {
List<User> findUserByPage(Map<String, Object> map);
long findUserCount();
}
UserControl
@Controller("userControl")
public class UserControl {
@Autowired
UserMapper userMapper;
public Pager<User> findByUserPager(int page, int size){
Map<String, Object> params = new HashMap<String, Object>();
params.put("page", (page-1)*size);
params.put("size", size);
List<User> list = userMapper.findUserByPage(params);
Pager<User> pager = new Pager<User>();
pager.setData(list);
pager.setTotal(userMapper.findUserCount());
return pager;
}
}
UserMapper.xml
<mapper namespace="com.lucas.mybatis.mapper.UserMapper">
<select id="findUserByPage" resultType="com.lucas.mybatis.model.User" >
select * from user limit #{page},#{size}
select>
<select id="findUserCount" resultType="long">
select count(1) from user
select>
mapper>
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserControl userControl = (UserControl) applicationContext.getBean("userControl");
Pager<User> userPager = userControl.findByUserPager(1,10);
userPager.setPage(1);
userPager.setSize(10);
System.out.println(userPager);
}
}
首先定一个拦截器,拦截器会拦截所有以ByPage结尾的方法,然后拼接sql 语句的limit关键字实现分页
@Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = {
Connection.class, Integer.class})})
public class MyPageInterceptor implements Interceptor {
private int page;
private int size;
@SuppressWarnings("unused")
private String dbType;
@SuppressWarnings("unchecked")
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
while (metaObject.hasGetter("h")) {
Object object = metaObject.getValue("h");
metaObject = SystemMetaObject.forObject(object);
}
while (metaObject.hasGetter("target")) {
Object object = metaObject.getValue("target");
metaObject = SystemMetaObject.forObject(object);
}
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
String mapId = mappedStatement.getId();
if (mapId.matches(".+ByPage$")) {
ParameterHandler parameterHandler = (ParameterHandler) metaObject.getValue("delegate.parameterHandler");
Map<String, Object> params = (Map<String, Object>) parameterHandler.getParameterObject();
page = (int) params.get("page");
size = (int) params.get("size");
String sql = (String) metaObject.getValue("delegate.boundSql.sql");
sql += " limit " + (page - 1) * size + "," + size;
metaObject.setValue("delegate.boundSql.sql", sql);
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
String limit = properties.getProperty("limit", "10");
this.page = Integer.parseInt(limit);
this.dbType = properties.getProperty("dbType", "mysql");
}
}
修改controller的findByUserPager
方法,拦截器已经自动帮我们算好了page和size的值
public Pager<User> findByUserPager(int page, int size){
Map<String, Object> params = new HashMap<String, Object>();
params.put("page", page);
params.put("size", size);
List<User> list = userMapper.findUserByPage(params);
Pager<User> pager = new Pager<User>();
pager.setData(list);
pager.setTotal(userMapper.findUserCount());
return pager;
}
UserMapper.xml
<mapper namespace="com.lucas.mybatis.mapper.UserMapper">
<select id="findUserByPage" resultType="com.lucas.mybatis.model.User" >
select * from user
select>
<select id="findUserCount" resultType="long">
select count(1) from user
select>
mapper>
Spring
配置文件中添加拦截器
<bean id="myPageInterceptor" class="com.lucas.mybatis.MyPageInterceptor"/>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource">property>
<property name="configLocation" value="mybatis-config.xml">property>
<property name="plugins" ref="myPageInterceptor"/>
bean>
运行结果同上
还可以利用知名的Mybatis
开源分页框架 PageHelper
来实现分页,该方法无须自己实现拦截器
官网:https://github.com/pagehelper/Mybatis-PageHelper
首先pom.xml文件中引入依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
修改Spring配置文件
<!-- 配置Mybatis工厂,指定数据源,SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<!-- 配置mapper.xml文件 -->
<property name="configLocation" value="mybatis-config.xml"></property>
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<!--使用下面的方式配置参数,一行配置一个 -->
<value>
params=value1
</value>
</property>
</bean>
</array>
</property>
</bean>
修改UserControl
的findByUserPager
方法
@Controller("userControl")
public class UserControl {
@Autowired
UserMapper userMapper;
public Pager<User> findByUserPager(int page, int size){
PageHelper.startPage(page,size);
List<User> list = userMapper.findUserByPage();
Pager<User> pager = new Pager<User>();
pager.setData(list);
pager.setTotal(userMapper.findUserCount());
return pager;
}
}
运行结果同上