本猿这几周因为某某原因出去面试了,在与面试官斗智斗勇中落败,还好有瞄了几份卷子回来;
下面来一一讲解下吧
mybatis分页
1.mybatis是如何分页的,分页插件的原理是什么?
mybatis有四种分页方式
(1)数组分页
先查询处所有数据,然后再list中截取需要的部分;
例如:
mapper:
List<Student> queryStudentsByArray();
xml
<select id="queryStudentsByArray" resultMap="studentmapper">
select * from student
</select>
service
public List<Student> queryStudentsByArray(int currPage, int pageSize) {
//查询全部数据
List<Student> students = studentMapper.queryStudentsByArray();
//从第几条数据开始
int firstIndex = (currPage - 1) * pageSize;
//到第几条数据结束
int lastIndex = currPage * pageSize;
return students.subList(firstIndex, lastIndex); //直接在list中截取
}
(2)sql分页
就是执行sql时做分页,一般用的是limit index, pageSize这种形式
<select id="queryStudentsBySql" parameterType="map" resultMap="studentmapper">
select * from student limit #{currIndex} , #{pageSize}
</select>
(3)拦截器分页
说实话,目前我还没搞懂啥是拦截器分页,略过
(4)RowBounds分页
这个也很少用到,网上查了下是这么说的:
数据量小时,RowBounds不失为一种好办法。但是数据量大时,实现拦截器就很有必要了。
mybatis接口加入RowBounds参数
public List<UserBean> queryUsersByPage(String userName, RowBounds rowBounds);
service
@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.SUPPORTS)
public List<RoleBean> queryRolesByPage(String roleName, int start, int limit) {
return roleDao.queryRolesByPage(roleName, new RowBounds(start, limit));
}
当然除了上面四种还可以用分页插件来实现,实现原理:
基于拦截器拦截待执行的SQL语句,然后修改最终执行SQL语句,属于物理分页;
接口绑定
接口绑定有两种方式,一种是注解绑定,直接在接口的方法上加上@Select、@Update等注解包含sql来绑定
另一种是通过xml里面写sql来绑定,这种要在xml映射文件里面的namespace和接口的全路径名保持一致
延时加载
它的原理是,使用 CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用 a.getB().getName(),拦截器 invoke()方法发现a.getB()是 null 值,那么就会单独发送事先保存好的查询关联 B 对象的 sql,把 B 查询上来,然后调用a.setB(b),于是 a 的对象 b 属性就有值了,接着完成 a.getB().getName()方法的调用。这就是延迟加载的基本原理。