MyBatis3的Plugins功能使用
1、这是什么?
根据官方介绍,这个功能可以让你在已映射语句执行过程中的某一点进行拦截调用。其实就是MyBatis给用户留了几个切入点,通过这些切入点,用户可以自己实现的功能。根据官方介绍,这些切入点(方法)包括以下几个:
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
这是四个接口以及接口的方法,这些接口是MyBatis在执行sql语句时会执行的方法。用户就可以通过这些方法进行切入,实现自己的逻辑。
接下来,我们通过实现一个打印sql语句的功能来进行演示。
2、通过Plugin实现打印SQL语句
2.1 创建表并初始化数据
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`age` int(3) DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
`sex` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
插入测试数据
INSERT INTO `t_user` VALUES (1, '张三', 4, 'OUT', '男');
INSERT INTO `t_user` VALUES (2, '李四', 5, 'OUT', '男');
INSERT INTO `t_user` VALUES (3, '王五', 5, 'OUT', '男');
2.2、构建项目
创建一个maven项目,并引入相关jar包,pom.xml文件如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mybatis.plugins</groupId>
<artifactId>mybatis-plugins-study</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
创建包及类
2.3、类介绍
User类,与数据库表对应的实体类
package com.mybatis.plugins.study.entity;
/**
* @author guandezhi
* @date 2019/7/2 17:40
*/
public class User {
private int id;
private String name;
private int age;
private String address;
private String sex;
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("User{");
sb.append("id=").append(id);
sb.append(", name='").append(name).append('\'');
sb.append(", age=").append(age);
sb.append(", address=").append(address);
sb.append(", sex=").append(sex);
sb.append('}');
return sb.toString();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
UserMapper接口,实现具体的sql语句,这里为了方便,我们使用MyBatis的注解方式
package com.mybatis.plugins.study.mapper;
import com.mybatis.plugins.study.entity.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.type.Alias;
import java.util.List;
/**
* @author guandezhi
* @date 2019/7/2 17:49
*/
@Alias(value = "userMapper")
public interface UserMapper {
/**
* 查询方法
* @param id 用户id
* @param name 用户姓名
* @return 结果集合
*/
@Select("select * from t_user where id = #{param1} and name = #{param2}")
List<User> select(@Param("idParam") int id, @Param("nameParam") String name);
}
在这里简单说明一下注解sql里的参数问题,一般情况下,如果只有一个参数,我们不需要写@Param注解也是可以的,如果有多个参数,则需要对每个参数使用@Param注解指定参数名字,或者也可以使用MyBatis提供的默认参数方式,就是示例中使用的方式,按照参数的顺序分别为param1、param2…。
接下来,就是Plugins的核心代码了,LogInterceptor类,按照官方文档,如果我们需要使用Plugins的功能,需实现 Interceptor 接口
package com.mybatis.plugins.study.interceptor;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.*;
import java.sql.Connection;
import java.util.List;
import java.util.Properties;
/**
* @author guandezhi
* @date 2019/7/2 17:46
*/
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class LogInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
BoundSql boundSql = statementHandler.getBoundSql();
// 原始sql
String sql = boundSql.getSql();
Sys