一、前言

Mybatis支持插件实现接口 org.apache.ibatis.plugin.Interceptor 来达到插件的功能,最常见的插件就是分页插件。
引入插件 pagehelper

  1. <dependency>
  2. <groupId>com.github.pagehelper</groupId>
  3. <artifactId>pagehelper</artifactId>
  4. <version>5.1.2</version>
  5. </dependency>
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6. <settings>
  7. <setting name="logImpl" value="STDOUT_LOGGING" />
  8. <setting name="mapUnderscoreToCamelCase" value="true"/>
  9. </settings>
  10. <!--配置PageHelper分页插件拦截器-->
  11. <plugins>
  12. <plugin interceptor="com.github.pagehelper.PageInterceptor">
  13. <property name="offsetAsPageNum" value="true"/>
  14. <property name="helperDialect" value="mysql"/>
  15. <property name="rowBoundsWithCount" value="true"/>
  16. <property name="reasonable" value="true"/>
  17. </plugin>
  18. </plugins>
  19. <environments default="mysql">
  20. <environment id="mysql">
  21. <!-- 配置事务-->
  22. <transactionManager type="JDBC"></transactionManager>
  23. <!-- 配置连接池-->
  24. <dataSource type="POOLED">
  25. <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
  26. <property name="url" value="jdbc:mysql://localhost:3306/smiler_user?useUnicode=true&amp;characterEncoding=utf8"/>
  27. <property name="username" value="root"/>
  28. <property name="password" value="123456"/>
  29. </dataSource>
  30. </environment>
  31. </environments>
  32. <!-- 配置映射文件的位置-->
  33. <mappers>
  34. <!-- <mapper resource="user/mapper/UserMapper.xml"></mapper>-->
  35. <!-- 用于指定dao接口所在的包,指定之后就不再需要写,mapper resources class mapper.xml-->
  36. <package name="user.mapper"/>
  37. </mappers>
  38. </configuration>
  1. public static void main(String[] args) throws IOException {
  2. InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
  3. SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
  4. SqlSessionFactory factory = builder.build(in);
  5. SqlSession session = factory.openSession();
  6. //获得dao 的代理对象
  7. PageHelper.startPage(0,2);
  8. UserMapper userMapper = session.getMapper(UserMapper.class);
  9. List<User> user = userMapper.queryByName("king");
  10. PageHelper.clearPage();
  11. // User user2 = userMapper.queryById(21);
  12. System.out.println(user.toString());
  13. // userMapper.deleteById("1");
  14. // userMapper.deleteByName("'dasd' or 1=1");
  15. session.commit();
  16. }

二、源码分析

1、doQuery

在org.apache.ibatis.executor.SimpleExecutor#doQuery 方法执行的时候,会使用configuration.newStatementHandler 来生成一个StatementHandler。
image.png

2、configuration.newStatementHandler

在 newStatementHandler 方法中,会使用拦截器来生成新的statementHandler,假如使用了分页插件,则会对sql进行重写。
image.png
image.png

InterceptorChain使用到了责任链模式:https://www.yuque.com/wangchao-volk4/udv4ny/rlz4pm

image.png
这里最终会返回一个代理的对象。

3、Interceptor

�PageHelper就是实现了这个接口 org.apache.ibatis.plugin.Interceptor
image.png

关于pageHelper究竟是如何分页的,后面再说