springboot结合mybatis使用pageHelper插件进行分页查询
1、pom相关依赖引入
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--pagehelper-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
</dependencies>
2、application配置
# MyBatis mybatis: #数据库映射对象包路径 type-aliases-package: com.example.springbootpagehelper.domain #mapper对应xml路径 mapper-locations: classpath:/mybatis/*.xml #sql打印配置 configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # PageHelper分页插件配置 pagehelper: #分页插件会自动检测当前的数据库链接,自动选择合适的分页方式。 helper-dialect: mysql #分页合理化参数,默认值为false。当该参数设置为 true 时,pageNum<=0 时会查询第一页, pageNum>pages(超过总数时),会查询最后一页。默认false 时,直接根据参数进行查询。 reasonable: true #支持通过 Mapper 接口参数来传递分页参数,默认值false,分页插件会从查询方法的参数值中,自动根据上面 params 配置的字段中取值,查找到合适的值时就会自动分页。 support-methods-arguments: true #为了支持startPage(Object params)方法,增加了该参数来配置参数映射,用于从对象中根据属性名取值, 可以配置 pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值, 默认值为pageNum=pageNum。 params: count=countSql
3、代码编写分页查询
@Autowired private UserService userService; @RequestMapping(value = "listUser") public List<User> listUser(@RequestParam(defaultValue = "1") int pageNo, @RequestParam(defaultValue = "10") int pageNum) { //分页查询,包括分页和总数查询,第三个参数是控制是否计算总数,默认是true,true为查询总数,分页效果只对其后的第一个查询有效。 PageHelper.startPage(pageNo, pageNum); //有分页 List<User> userList = userService.listUser(); //没分页 List<User> users = userService.listUser(); return userList; }
对返回结果用PageInfo进行封装
@RequestMapping(value = "pageInfoUser") public PageInfo<User> pageInfoUser(@RequestParam(defaultValue = "1") int pageNo, @RequestParam(defaultValue = "10") int pageNum) { //分页查询,包括分页和总数查询,第三个参数是控制是否计算总数,默认是true,true为查询总数,分页效果只对其后的第一个查询有效。 PageHelper.startPage(pageNo, pageNum); PageInfo<User> userPageInfo = userService.pageInfoUser(); return userPageInfo; }
UserService类
@Override public PageInfo<User> pageInfoUser() { return new PageInfo<>(userMapper.selectUserPage()); }
4、分页安全性问题
PageHelper 方法使用了静态的 ThreadLocal 参数,分页参数和线程是绑定的。
一般只要保证在 PageHelper 方法调用后紧跟 MyBatis 查询方法,这就是安全的。因为 PageHelper 在 finally 代码段中自动清除了 ThreadLocal 存储的对象。
如果代码在进入 Executor 前发生异常,就会导致线程不可用,导致 ThreadLocal 参数被错误的使用。
下面这样的代码是不安全的用法:
PageHelper.startPage(1, 10); List<Country> list; if(param1 != null){ list = countryMapper.selectIf(param1); } else { list = new ArrayList<Country>(); }
这种情况下由于 param1 存在 null 的情况,就会导致 PageHelper 生产了一个分页参数,但是没有被消费,这个参数就会一直保留在这个线程上。当这个线程再次被使用时,就可能导致不该分页的方法去消费这个分页参数,这就产生了错误的分页。
应该写成下面这个样子:
List<Country> list; if(param1 != null){ PageHelper.startPage(1, 10); list = countryMapper.selectIf(param1); } else { list = new ArrayList<Country>(); }
或者可以手动清理 ThreadLocal 存储的分页参数,如下所示:
List<Country> list; if(param1 != null){ PageHelper.startPage(1, 10); try{ list = countryMapper.selectAll(); } finally { PageHelper.clearPage(); } } else { list = new ArrayList<Country>(); }