在日常开发中,多记录的列表查询可能会遇到分页处理的场景,在springboot项目中传统是引入mybatis组件进行持久化,然后通过pagehelper组件进行分页实现。下面体验一下在springboot项目中引入mybatisplus组件,通过其自带分页插件实现分页功能。
MyBatis Plus是一个MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
Mybatis Plus可以节省大量时间,所有的CRUD代码都可以自动化完成。MyBatis Plus自带分页插件(即BaseMapper接口中的selectPage()方法),只要简单的配置即可实现分页功能。
pom.xml文件中引入依赖
com.baomidou
mybatis-plus-boot-starter
com.baomidou
dynamic-datasource-spring-boot-starter
添加分页配置类
@Configuration
public class MybatisPlusConfig {
/**
* 分页插件(官网最新)
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
添加service层代码,分页的所有数据都在userPage对象中封装着,所以可以调用userPage对象的一系列方法对分页数据进行操作。
@Slf4j
@Service
public class SysUserServiceImpl implements SysUserService {
@Autowired
private SysUserMapper userMapper;
@Override
public Page listPage1(Page page, QueryWrapper queryWrapper) {
return userMapper.selectPage(page, queryWrapper);
}
@Override
public PagerModel listPage2(Page page, QueryWrapper queryWrapper) {
Page userIPage = userMapper.selectPage(page, queryWrapper);
// 分页的所有数据都在userPage对象中封装着
// 获取总页数
long pages = userIPage.getPages();
//一页显示几条数据
long size = userIPage.getSize();
// 获取当前页
long current = userIPage.getCurrent();
// 获取当前页数据集合
List records = userIPage.getRecords();
// 获取总记录数
long total = userIPage.getTotal();
// 当前页是否有下一页
boolean hasNext = userIPage.hasNext();
// 当前页是否有上一页
boolean hasPrevious = userIPage.hasPrevious();
System.out.println("总页数pages=" + pages);
System.out.println("当前页current=" + current);
System.out.println("当前页显示几条数据size=" + size);
System.out.println("当前页数据集合records=" + records);
System.out.println("总记录数total=" + total);
System.out.println("是否有下一页hasNext=" + hasNext);
System.out.println("是否有上一页hasPrevious=" + hasPrevious);
return new PagerModel<>(userIPage.getTotal(), records);
}
}
添加controller层代码
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private SysUserService userService;
/**
* 分页列表
* @param keyword
* @param pageNum
* @param pageSize
* @return
*/
@GetMapping("/listPage1")
public Page listPage1(@RequestParam(value = "keyword", defaultValue = "") String keyword,
@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
@RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize) {
// 条件构造器
QueryWrapper queryWrapper = new QueryWrapper<>();
// 模糊查询Like
queryWrapper.like("nickname", keyword);
// 分页插件
Page page = new Page(pageNum, pageSize);
// 查询数据
return userService.listPage1(page, queryWrapper);
}
/**
* 自定义分页对象,分页列表
* @param keyword
* @param pageNum
* @param pageSize
* @return
*/
@GetMapping("/listPage2")
public PagerModel listPage2(@RequestParam(value = "keyword", defaultValue = "") String keyword,
@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
@RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize) {
// 条件构造器
QueryWrapper queryWrapper = new QueryWrapper<>();
// 模糊查询Like
queryWrapper.like("nickname", keyword);
// 分页插件
Page page = new Page(pageNum, pageSize);
// 查询数据
return userService.listPage2(page, queryWrapper);
}
}
自定义列表返回对象
@Data
@Builder(toBuilder = true)
public class PagerModel implements Serializable {
private static final long serialVersionUID = 4804053559968742915L;
/**
* 总记录数
*/
private long total;
/**
* 每页的查询结果集
*/
private List rows = new ArrayList();
/**
* 获取总页数
*/
private long pages;
/**
* 获取当前页
*/
private long current;
/**
* 当前页显示几条数据
*/
private long size;
/**
* 当前页是否有下一页
*/
private boolean hasNext;
/**
* 当前页是否有上一页
*/
private boolean hasPrevious;
public PagerModel() {
}
public PagerModel(long total, List rows) {
this.total = total;
this.rows = rows;
}
public PagerModel(long total, List rows, long pages, long current) {
this.total = total;
this.rows = rows;
this.pages = pages;
this.current = current;
}
public PagerModel(long total, List rows, long pages, long current, long size) {
this.total = total;
this.rows = rows;
this.pages = pages;
this.current = current;
this.size = size;
}
public PagerModel(long total, List rows, long pages, long current, boolean hasNext, boolean hasPrevious) {
this.total = total;
this.rows = rows;
this.pages = pages;
this.current = current;
this.hasNext = hasNext;
this.hasPrevious = hasPrevious;
}
public PagerModel(long total, List rows, long pages, long current, long size, boolean hasNext, boolean hasPrevious) {
this.total = total;
this.rows = rows;
this.pages = pages;
this.current = current;
this.size = size;
this.hasNext = hasNext;
this.hasPrevious = hasPrevious;
}
}
访问:http://localhost:8805/first/user/listPage1,结果如下
访问:http://localhost:8805/first/user/listPage2,结果如下
日志打印如下
异常信息如下
Caused by: java.sql.SQLFeatureNotSupportedException: null
at com.alibaba.druid.pool.DruidPooledResultSet.getObject(DruidPooledResultSet.java:1771)
at com.p6spy.engine.wrapper.ResultSetWrapper.getObject(ResultSetWrapper.java:1649)
at org.apache.ibatis.type.LocalDateTimeTypeHandler.getNullableResult(LocalDateTimeTypeHandler.java:38)
at org.apache.ibatis.type.LocalDateTimeTypeHandler.getNullableResult(LocalDateTimeTypeHandler.java:28)
at org.apache.ibatis.type.BaseTypeHandler.getResult(BaseTypeHandler.java:81)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.applyAutomaticMappings(DefaultResultSetHandler.java:521)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.getRowValue(DefaultResultSetHandler.java:402)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValuesForSimpleResultMap(DefaultResultSetHandler.java:354)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValues(DefaultResultSetHandler.java:328)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSet(DefaultResultSetHandler.java:301)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSets(DefaultResultSetHandler.java:194)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:65)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:79)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:63)
at com.sun.proxy.$Proxy247.query(Unknown Source)
at com.baomidou.mybatisplus.core.executor.MybatisSimpleExecutor.doQuery(MybatisSimpleExecutor.java:67)
at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:324)
at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156)
at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:136)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:147)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:76)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:426)
... 106 common frames omitted
出现上述异常是由于druid和Mybatis plus依赖版本的问题。
druid版本在1.1.21之前是不支持LocalDateTime等新日期处理方式的,但是Mybatis plus在3.3.1之后是支持的。因此在SQL查询过程中,这两者就产生了冲突。
解决方法:把druid版本提高到1.2.6(不建议降低Mybatis plus版本),改完之后,异常解决。注:确保项目中的依赖或隐藏依赖中的druid版本提高到1.1.21版本以上。