文章目录
执行一条查询语句的大致流程
获得一个 SqlSession(DefaultSqlSession, 门面模式, 最终调用 Executor 执行对应的方法),
解析配置文件, 获取 Configuration 对象, 构建 SqlSessionFactory, Configuration 中最重要的两个属性如下
- environment: 封装了事务工厂和 DataSource, 可以 getConnection()
- mapperdStatements: 封装了各个增删查改 SQL 语句的全部信息(SQL 本体, 入参, 出参, …)
SQL 本体被解析成为 SqlSource, 由一个个的 SqlNode(最顶层是 MixedSqlNode, 字符串是 StaticTextSqlNode, where 条件是 WhereSqlNode, if 条件是 IfSqlNode(if 的表达式由 ognl 提供技术支持), 还有 ChooseSqlNode, TrimSqlNode, TextSqlNode,ForEachSqlNode, …, 不同节点对应不同 SqlNode) 组成, 遵循书写时的排列和包含关系, 解析的时候使用责任链的形式解析, 最终获得一条完整的 SQL 语句(这时#{}等参数还没有被替换)
设置参数, 先把 SQL 中的参数都提取出来, 并替换成问号, 将参数分装成一个 ParameterMapping,
根据传入的参数值, 获取其类型, 从 Configuration 中的 TypeHandlerRegistry 中获取对应参数类型的 TypeHandler, 调用其 setNonNullParameter 方法给 PreparedStatement 设置对应位置的参数,
执行 SQL, 获取结果集, 结果集中有字段名和字段值, 根据 ResultMap 将其转换为对应的返回值类型
MyBatis 共有如下5种执行器, 前3种是基础的
- SimpleExecutor, 默认, 每次都会解析 SQL 语句
- ReuseExecutor, 只会解析一遍 SQL, 不会每次都重复解析
- BatchExecutor, 用于执行批量操作
- CatchingExecutor(开启二级缓存才会创建, 然后由其装饰(委托)前3种 Executor, 提供了二级缓存的能力)
- BaseExecutor(前3种执行器的父类, 提供了一级缓存的能力)
Plugin 使用责任链加代理的方式增强 MyBatis 内部的4大核心组件
- Executor: update, query, flushStatements, commit, rollback, getTransaction, close, isClosed
- ParameterHandler: 处理参数, getParameterObject, setParameters
- ResultSetHandler: 处理结果集, handleResultSets, handleOutputParameters
- StatementHandler: prepare, parameterize, batch, update, query
使用的时候, 自定义一个 Plugin 类, 加注解 @Intercepts({@Signature(type=4核心组件之一,method=“组件内的方法名”, args={确定参数类型, 因为方法可用重写})}), 举个例子, 当你给 Executor 的 query 方法加了一个插件, 拦截并修改其 SQL, 添加了分页 limit 的功能, 然后在配置文件中的 plugins 内添加 plugin 标签