MyBatis 入门教程之七
大纲
- MyBatis 入门教程之一
- MyBatis 入门教程之二
- MyBatis 入门教程之三
- MyBatis 入门教程之四
- MyBatis 入门教程之五
- MyBatis 入门教程之六
- MyBatis 入门教程之七
- MyBatis 入门教程之八
MyBatis 四大对象
四大对象介绍
MyBatis 的四大对象包括:Executor、StatementHandler、ParameterHandler、ResultSetHandler。四大对象的工作职责如下:
Executor(执行器)
:负责整个 SQL 执行过程的总体控制StatementHandler(语句处理器)
:负责和 JDBC 层交互,包括预编译 SQL 语句和执行 SQL 语句,以及调用ParameterHandler
设置参数ParameterHandler(参数处理器)
:负责设置预编译参数ResultSetHandler(结果集处理器)
:负责将 JDBC 查询结果映射到 JavaBean 对象
四大对象的工作流程
MyBatis 插件开发
本节所需的案例代码,可以直接从 GitHub 下载对应章节 mybatis-lesson-20
。
插件介绍
- MyBatis 在四大对象的创建过程中,都允许有插件进行介入。插件可以利用动态代理机制一层层的包装目标对象,从而实现在目标对象指向目标方法之前进行拦截的效果。
- MyBatis 自定义插件是非常简单的,只需实现
Interceptor
接口,并指定想要拦截哪个对象的哪个方法,即可介入四大对象的任何一个方法的执行。 - MyBatis 允许在已映射语句执行过程中的某一点进行拦截调用。
- 默认情况下,MyBatis 允许使用插件来拦截的方法包括:
Executor
:update, query, flushStatements, commit, rollback, getTransaction, close, isClosedStatementHandler
:prepare, parameterize, batch, update, queryParameterHandler
:getParameterObject, setParametersResultSetHandler
:handlerResultSets, handlerOuutputParameters
特别注意
自定义 MyBatis 插件时,如果你想做的不仅仅是监控方法的调用,那么你最好相当了解要重写的方法的行为。因为在试图修改或重写已有方法的行为时,很可能会破坏 MyBatis 的核心模块。这些都是更底层的类和方法,所以使用插件的时候需要特别小心。
插件原理
- 在 MyBatis 的全局配置文件里注册插件后,会按照插件的配置顺序,依次调用插件的
plugin()
方法来生成被拦截对象的动态代理对象 - 存在多个插件时,会依次生成目标对象的动态代理对象,层层包裹,先声明的先包裹,以此形成代理链
- 目标方法执行时,是按照插件配置信息的逆向顺序来执行
intercept()
方法,即先配置的插件会后执行 - 使用多个插件的情况下,往往需要在某个插件中分离出来目标对象,可以借助 MyBatis 提供的
SystemMateObject
类来获取最后一层的h
以及target
属性的值
插件开发案例
Interceptor 接口
Interceptor.intercept()
:拦截目标方法的执行Interceptor.plugin()
:创建动态代理对象,可以使用 MyBatis 提供的Plugin
类的wrap
方法Interceptor.setProperties()
:注入配置插件时设置的属性
插件开发案例一
- 实现
Interceptor
接口,并通过插件签名指定要拦截哪个对象的哪个方法
1 | package com.clay.mybatis.plugin; |
- 在 MyBatis 的全局配置文件中注册插件
1 | <configuration> |
- 上面自定义的插件将会拦截在
StatementHandler
实例中所有的prepare()
方法调用,MyBatis 执行普通的 SQL 查询语句后,控制台输出的日志信息如下:
1 | MyFirstPlugin ==> 要包装的对象: org.apache.ibatis.executor.CachingExecutor@69fb6037 |
插件开发案例二
在下面的案例代码里,演示了如何动态更改 SQL 语句运行时的参数,例如查询员工信息时,动态更改查询的员工 ID 为 11
。
- Mapper 接口
1 | public interface EmployeeMapper { |
- SQL 映射文件
1 | <mapper namespace="com.clay.mybatis.dao.EmployeeMapper"> |
- 自定义插件
1 | package com.clay.mybatis.plugin; |
- 注册插件
1 | <configuration> |
- 业务代码
1 | public class MyBatisApplication { |
- 执行结果
1 | 22:36:57,053 DEBUG getEmpById:137 - ==> Preparing: select id, last_name as lastName, gender, email from t_employee where id = ? |
多个插件的执行顺序
MyBatis 在创建动态代理时,是按照插件的配置顺序依次调用 plugin()
方法创建层层的代理对象,但插件的 intercept()
方法是按照配置信息的逆向顺序来执行,即先配置的插件会后执行。
- 在上面案例代码的基础上,增加一个 MyBatis 插件
1 | package com.clay.mybatis.plugin; |
- 在 MyBatis 的全局配置文件中同时注册多个插件
1 | <configuration> |
- MyBatis 执行普通的 SQL 查询语句后,控制台输出的日志信息如下:
1 | MyFirstPlugin ==> 要包装的对象: org.apache.ibatis.executor.CachingExecutor@36d585c |
MyBatis 代码生成器
MyBatis Generator(简称 MBG),是一个专门为 MyBatis 框架使用者定制的代码生成器(逆向工程),可以快速地根据数据库表生成对应的 SQL 映射文件、Mapper 接口以及 JavaBean 类。支持基本的增删改查,以及 QBC 风格的条件查询。但是像数据库表连接、存储过程等这些复杂 SQL 的定义需要开发者手工编写。更多的介绍内容,可查看 GitHub 仓库 和 MyBatis 官方文档。
准备工作
下述的案例代码是基于以下的数据库表结构编写的,因此需要提前执行 SQL 语句来初始化数据库。
1 | CREATE DATABASE `mybatis_lesson` DEFAULT CHARACTER SET utf8mb4; |
使用案例
本节所需的案例代码,可以直接从 GitHub 下载对应章节 mybatis-lesson-19
。
引入 Maven 依赖
1 | <dependency> |
创建 XML 配置文件
在项目的 src/test/resources
目录下创建 mybatis-generator.xml
配置文件,其中的配置内容如下:
1 |
|
上述 XML 配置文件里的 targetRuntime="MyBatis3Simple"
表示只生成基础的 CRUD 代码和少量动态 SQL 语句,可选值有 MyBatis3DynamicSql | MyBatis3Kotlin | MyBatis3 | MyBatis3Simple
。值得一提的是,在企业项目开发中,用得最多的是 targetRuntime="MyBatis3"
,它支持复杂条件查询(QBC 查询)和自动生成大量动态 SQL 语句。MyBatis Generator 完整的 XML 标签介绍可看 这里。
运行代码生成器
MyBatis Generator (MBG) 可以通过以下方式运行:
- From the command prompt with an XML configuration
- As an Ant task with an XML configuration
- As a Maven Plugin
- From another Java program with an XML configuration
- From another Java program with a Java based configuration
- As an Eclipse Feature
这里采用 Java 代码 + XML 配置文件的方式运行代码生成器,示例代码如下:
1 | import java.io.File; |
最后会在项目的目录内自动生成 JavaBean 类、Mapper 接口和 SQL 映射文件,项目的目录结构图如下: