我们实现查询除了
@org.junit.Test
public void test02(){
SqlSession session = MybatisUtil.getSession();
UserDao mapper = session.getMapper(UserDao.class);
List<User> allUser = mapper.getAllUser();
session.close();
for (User user : allUser) {
System.out.println(user);
}
}
还有这样的方式,Mybatis官网有介绍
@org.junit.Test
public void test06(){
SqlSession session = MybatisUtil.getSession();
//参数是接口的全限定类名加包名
List<User> users = session.selectList("com.dongmu.dao.UserDao.getAllUser");
for (User user : users) {
System.out.println(user);
}
session.close();
}
那么我们下面就学习一下
@org.junit.Test
public void test07(){
RowBounds bounds =new RowBounds(0,3);
SqlSession session = MybatisUtil.getSession();
List<User> users = session.selectList("com.dongmu.dao.UserDao.getAllUser",null,bounds);
for (User user : users) {
System.out.println(user);
}
session.close();
}
这里总结一下自己注意到的细节,它的sql语句我们发现是查询的所有的,所以它实际上是逻辑分页,也就是说把结果全部查询除了然后进行按游标分页。
但是真的是这样吗?
RowBounds 表面是在“所有”数据中检索数据,其实并非是一次性查询出所有数据,因为 MyBatis 是对jdbc 的封装,在 jdbc 驱动中有一个 Fetch Size 的配置,它规定了每次最多从数据库查询多少条数据,假如你要查询更的数据,它会在你执行 next()的时候,去查询更多的数据。就好比你去自动取款机取 10000 元,但取款机每次最多能取 2500 元,所以你要取 4 次才能把钱取完。只是对于 jdbc 来说,当你调用 next()的时候会自动帮你完成查询工作。这样做的好处可以有效的防止内存溢出。
物理分页:物理分页就是数据库本身提供了分页方式,如MySQL的limit,oracle的rownum ,好处是效率高,不好的地方就是不同数据库有不同的搞法
逻辑分页:利用游标分页,好处是所有数据库都统一,坏处就是因为先查询到所有数据,所有效率低。
下面我们再介绍一个分页插件PageHelper
使用方式:
加入依赖:
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
在mybatis的主配置文件中,在<environments>之前加入
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor" />
</plugins>
在进行失去了查询之前使用方法:
PageHelper.startPage(pageNum,pageSize);
查询结果
可以发现我们的PageHelper用到的是PreparedStatement进行的物理分页查询。
如果是再springboot项目中使用那就更简单了
直接引入依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.10</version>
</dependency>
使用分页的时候先PageHelper.startPage(page,limit);即可分页
PageHelper 使用了静态的 ThreadLocal 参数,让线程绑定了分页参数, 这个参数如果没被使用就会一直留在那儿,当这个线程再次被使用时,就可能导致不该分页的方法去消费这个分页参数,这就产生了莫名其妙的分页。
参考地址
什么时候会导致不安全的分页? PageHelper 方法使用了静态的 ThreadLocal 参数,分页参数和线程是绑定的。
只要你可以保证在 PageHelper 方法调用后紧跟 MyBatis 查询方法,这就是安全的。因为 PageHelper 在 finally 代码段中自动清除了 ThreadLocal 存储的对象。
如果代码在进入 Executor 前发生异常,就会导致线程不可用,这属于人为的 Bug(例如接口方法和 XML 中的不匹配,导致找不到 MappedStatement 时), 这种情况由于线程不可用,也不会导致 ThreadLocal 参数被错误的使用。