MyBatis基础用法--插件开发

目录

插件简介

插件原理

插件编写

插件示例源码

ExecutorPlugin类

ParameterHandlerPlugin类

ResultSetHandlerPlugin类

StatementHandlerPlugin类


插件简介

MyBatis在四大对象(ExecutorParameterHandlerResultSetHandlerStatementHandler)创建过程中,都会有插件介入,插件可以利用动态代理机制一层层的包装目标对象,从而实现在目标对象执行目标方法之前进行拦截。

MyBatis中,借助于插件我们可以在SQL语句执行过程中的某一点进行拦截调用,这有点类似于Spring中的面向切面编程AOP。  

插件原理

MyBatis在创建四大对象(ExecutorParameterHandlerResultSetHandlerStatementHandler)的时候,每一个创建出来的对象并不会被直接返回,而是会对创建好的对象再次调用InterceptorChain.pluginAll(target)方法,该方法会获取到所有的拦截器(Interceptor,所有插件都要实现该接口),并依次调用每一个拦截器的Interceptor.plugin(target)方法为目标对象创建一个代理对象进行返回。这样,通过插件我们可以为四大对象中的每一个都创建出代理对象,从而可以拦截到四大对象执行的方法。 

public Object pluginAll(Object target) {
    for (Interceptor interceptor : interceptors) {
      target = interceptor.plugin(target);
    }
    return target;
}

默认情况下,MyBatis允许使用插件来拦截的方法调用包括:
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)  

插件编写

编写一个MyBatis插件类需要完成以下几个步骤:
1.插件类需实现org.apache.ibatis.plugin.Interceptor接口。
2.使用@Intercepts注解设置插件签名,指定该插件需要拦截哪些类的哪些方法。
3.将编写好的插件类注册到MyBatis的全局配置文件中。  

插件示例源码

ExecutorPlugin类

ExecutorPlugin插件用来拦截Executor类的query()方法。 

package org.mybatis.plugin;

import java.util.Properties;

import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

@Intercepts({
		@Signature(type = Executor.class, method = "query", args = {
				MappedStatement.class, Object.class, RowBounds.class,
				ResultHandler.class, CacheKey.class, BoundSql.class }),
		@Signature(type = Executor.class, method = "query", args = {
				MappedStatement.class, Object.class, RowBounds.class,
				ResultHandler.class })

})
public class ExecutorPlugin implements Interceptor {

	@Override
	public Object intercept(Invocation invocation) throws Throwable {

		Object target = invocation.getTarget();

		System.out.println("所拦截的目标对象-->" + target);
		System.out.println("所拦截的目标方法-->" + invocation.getMethod());
		System.out.println("所拦截的目标参数-->" + invocation.getArgs());
		System.out.println("所拦截的目标类型-->" + invocation.getClass());

		// 获取拦截对象的源数据信息
		MetaObject metaObject = SystemMetaObject.forObject(target);

		/*
		 * 如果全局配置中cacheEnabled设置为true,获取到的源对象将会是一个CachingExecutor对象
		 * 需要通过该对象的delegate属性来获取真正的Executor对象
		 */
		// Executor executor=(Executor) metaObject.getValue("delegate");
		// System.out.println("获取源对象的delegate属性-->"+executor);
		// System.out.println("获取真正Executor对象的configuration属性-->"+metaObject.getValue("delegate.configuration"));

		/*
		 * 实际的Executor对象的真正类型取决于取决于全局配置中defaultExecutorType的设置值
		 * SIMPLE(默认值)-->SimpleExecutor REUSE-->ReuseExecutor BATCH-->BatchExecutor
		 */
		System.out.println("获取源对象的configuration属性"
				+ metaObject.getValue("configuration"));
		
		//注意放行,否则将不会执行任何查询操作
		Object result = invocation.proceed();
		return result;
	}

	@Override
	public Object plugin(Object target) {
		// 可以使用Plugin.wrap(target, this)方法,利用当前对象来包装目标对象
		Object wrapper = Plugin.wrap(target, this);
		return wrapper;
	}

	@Override
	public void setProperties(Properties properties) {
		// 在<plugin/>标签中设置的property
		System.out.println(properties);

	}

}

ParameterHandlerPlugin类

ParameterHandlerPlugin插件用来拦截ParameterHandler类的getParameterObject()setParameters(PreparedStatement ps)方法。 

package org.mybatis.plugin;

import java.sql.PreparedStatement;
import java.util.Properties;

import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

@Intercepts({
		@Signature(type = ParameterHandler.class, method = "getParameterObject", args = {}),
		@Signature(type = ParameterHandler.class, method = "setParameters", args = { PreparedStatement.class })

})
public class ParameterHandlerPlugin implements Interceptor {

	@Override
	public Object intercept(Invocation invocation) throws Throwable {

		Object target = invocation.getTarget();

		System.out.println("所拦截的目标对象-->" + target);
		System.out.println("所拦截的目标方法-->" + invocation.getMethod());
		System.out.println("所拦截的目标参数-->" + invocation.getArgs());
		System.out.println("所拦截的目标类型-->" + invocation.getClass());

		// 获取目标对象的源数据信息
		MetaObject metaObject = SystemMetaObject.forObject(target);

		/*
		 * 获取到的源对象是DefaultParameterHandler类型
		 */
		System.out.println("获取源对象的typeHandlerRegistry属性-->"
				+ metaObject.getValue("typeHandlerRegistry"));
		System.out.println("获取源对象的mappedStatement属性-->"
				+ metaObject.getValue("mappedStatement"));
		System.out.println("获取源对象的parameterObject属性-->"
				+ metaObject.getValue("parameterObject"));
		System.out.println("获取源对象的boundSql属性-->"
				+ metaObject.getValue("boundSql"));
		System.out.println("获取源对象的configuration属性-->"
				+ metaObject.getValue("configuration"));

		// 注意放行,否则将不会执行任何查询操作
		Object result = invocation.proceed();
		return result;
	}

	@Override
	public Object plugin(Object target) {
		// 可以使用Plugin.wrap(target, this)方法,利用当前对象来包装目标对象
		Object wrapper = Plugin.wrap(target, this);
		return wrapper;
	}

	@Override
	public void setProperties(Properties properties) {
		// 在<plugin/>标签中设置的property
		System.out.println(properties);

	}

}

ResultSetHandlerPlugin类

ResultSetHandlerPlugin插件用来拦截ResultSetHandler类的handleResultSets(Statement stmt)方法。 

package org.mybatis.plugin;

import java.sql.Statement;
import java.util.Properties;

import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

@Intercepts({ @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = { Statement.class })

})
public class ResultSetHandlerPlugin implements Interceptor {

	@Override
	public Object intercept(Invocation invocation) throws Throwable {

		Object target = invocation.getTarget();

		System.out.println("所拦截的目标对象-->" + target);
		System.out.println("所拦截的目标方法-->" + invocation.getMethod());
		System.out.println("所拦截的目标参数-->" + invocation.getArgs());
		System.out.println("所拦截的目标类型-->" + invocation.getClass());

		// 获取目标对象的源数据信息
		MetaObject metaObject = SystemMetaObject.forObject(target);

		/*
		 * 获取到的源数据对象是DefaultResultSetHandler类型
		 */
		System.out.println("获取源对象的executor属性"
				+ metaObject.getValue("executor"));
		System.out.println("获取源对象的configuration属性"
				+ metaObject.getValue("configuration"));
		System.out.println("获取源对象的objectFactory属性"
				+ metaObject.getValue("objectFactory"));
		System.out.println("获取源对象的typeHandlerRegistry属性"
				+ metaObject.getValue("typeHandlerRegistry"));
		System.out.println("获取源对象的resultSetHandler属性"
				+ metaObject.getValue("resultHandler"));
		System.out.println("获取源对象的parameterHandler属性"
				+ metaObject.getValue("parameterHandler"));
		System.out.println("获取源对象的mappedStatement属性"
				+ metaObject.getValue("mappedStatement"));
		System.out.println("获取源对象的rowBounds属性"
				+ metaObject.getValue("rowBounds"));
		System.out.println("获取源对象的boundSql属性"
				+ metaObject.getValue("boundSql"));
		
		// 注意放行,否则将不会执行任何查询操作
		Object result = invocation.proceed();
		return result;
	}

	@Override
	public Object plugin(Object target) {

		// 可以使用Plugin.wrap(target, this)方法,利用当前对象来包装目标对象
		Object wrapper = Plugin.wrap(target, this);
		return wrapper;
	}

	@Override
	public void setProperties(Properties properties) {
		// 在<plugin/>标签中设置的property
		System.out.println(properties);

	}

}

StatementHandlerPlugin类

StatementHandlerPlugin插件用来拦截StatementHandler类的query(Statement statement, ResultHandler resultHandler)方法。 

package org.mybatis.plugin;

import java.sql.Statement;
import java.util.Properties;

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.ResultHandler;

@Intercepts({ @Signature(type = StatementHandler.class, method = "query", args = {
		Statement.class, ResultHandler.class })

})
public class StatementHandlerPlugin implements Interceptor {

	@Override
	public Object intercept(Invocation invocation) throws Throwable {

		Object target = invocation.getTarget();

		System.out.println("所拦截的目标对象-->" + target);
		System.out.println("所拦截的目标方法-->" + invocation.getMethod());
		System.out.println("所拦截的目标参数-->" + invocation.getArgs());
		System.out.println("所拦截的目标类型-->" + invocation.getClass());

		// 获取目标对象的源数据信息
		MetaObject metaObject = SystemMetaObject.forObject(target);

		/*
		 * 获取到的源数据对象是RoutingStatementHandler类型,这是一个包装类,
		 * 需要通过该对象的delegate属性来获取真正的StatementHandler对象。
		 * 真正的StatementHandler对象的类型取决于要处理的Statement的类型,
		 * 而Statement的类型又取决于Mapper中该增删改查标签的statementType属性的设置值:
		 * PREPARED(默认值)-->PreparedStatement STATEMENT-->Statement
		 * CALLABLE-->CallableStatement
		 */

		System.out
				.println("获取源对象的delegate属性" + metaObject.getValue("delegate"));
		System.out.println("获取真正的StatementHandler对象的configuration属性"
				+ metaObject.getValue("delegate.configuration"));
		System.out.println("获取真正的StatementHandler对象的objectFactory属性"
				+ metaObject.getValue("delegate.objectFactory"));
		System.out.println("获取真正的StatementHandler对象的typeHandlerRegistry属性"
				+ metaObject.getValue("delegate.typeHandlerRegistry"));
		System.out.println("获取真正的StatementHandler对象的resultSetHandler属性"
				+ metaObject.getValue("delegate.resultSetHandler"));
		System.out.println("获取真正的StatementHandler对象的parameterHandler属性"
				+ metaObject.getValue("delegate.parameterHandler"));
		System.out.println("获取真正的StatementHandler对象的executor属性"
				+ metaObject.getValue("delegate.executor"));
		System.out.println("获取真正的StatementHandler对象的mappedStatement属性"
				+ metaObject.getValue("delegate.mappedStatement"));
		System.out.println("获取真正的StatementHandler对象的rowBounds属性"
				+ metaObject.getValue("delegate.rowBounds"));
		System.out.println("获取真正的StatementHandler对象的boundSql属性"
				+ metaObject.getValue("delegate.boundSql"));

		// 注意放行,否则将不会执行任何查询操作
		Object result = invocation.proceed();
		return result;
	}

	@Override
	public Object plugin(Object target) {

		// 可以使用Plugin.wrap(target, this)方法,利用当前对象来包装目标对象
		Object wrapper = Plugin.wrap(target, this);
		return wrapper;
	}

	@Override
	public void setProperties(Properties properties) {
		// 在<plugin/>标签中设置的property
		System.out.println(properties);

	}

}

将编写好的插件类注册到MyBatis的全局配置文件中。 

<plugins>
	<plugin interceptor="org.mybatis.plugin.ParameterHandlerPlugin">
		<property name="name" value="root" />
		<property name="password" value="123456" />
	</plugin>
	<plugin interceptor="org.mybatis.plugin.ExecutorPlugin">
	</plugin>
	<plugin interceptor="org.mybatis.plugin.StatementHandlerPlugin">
	</plugin>
	<plugin interceptor="org.mybatis.plugin.ResultSetHandlerPlugin">
	</plugin>
</plugins>

  

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
手把手视频详细讲解项目开发全过程,需要的小伙伴自行百度网盘下载,链接见附件,永久有效。 课程简介 MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis基础上只做增强不做改变,为简化开发、提高效率而生。使用原生的Mybatis编写持久层逻辑时,所需要的代码是比较繁琐的,需要定义Mapper接口和Mapper.xml文件,每一个方法都需要编写对应的sql语句,会存在很多大量的重复工作,使用MP之后,对通用的方法做了高度的抽取,避免了很多重复工作,可以非常快速的实现了单表的各种增、删、改、查操作。除此之外,MP还提供了其他的高级功能,如:枚举、插件、ActiveRecord、SQL注入等。 本课程全面讲解了Mybatis-Plus框架的使用,从快速入门到原理分析再到插件的应用。每一个知识点都有案例进行演示学习,最终通过学习你将全面掌握MP的使用,从而使Mybatis的的开发更加的高效,达到事半功倍的效果。 适应人群 有一定的Java以及Mybatis框架的基础。 从0开始全面讲解Mybatis-Plus框架 l 快速入门 n Mybatis + MP 整合 n Spring + Mybatis + MP 整合 n SpringBoot + Mybatis + MP 整合 n 通用CRUD的全面讲解 n 配置 l 高级用法 n 条件构造器 n Oracle 主键Sequence n 通用枚举n ActiveRecord n 逻辑删除 l 插件 n 执行分析插件 n 性能分析插件 n 乐观锁插件 主讲内容 章节一:快速入门 1. Mybatis-Plus简介 2. 快速入门 3. 通用CRUD 4. 配置 5. 条件构造器 章节二:进阶 1. ActiveRecord 2. Oracle 主键Sequence 3. 插件 章节三:高级应用 1. Sql 注入器 2. 自动填充功能 3. 逻辑删除 4. 通用枚举 5. 代码生成器 6. MybatisX 快速开发插件
Mybatis-plus是MyBatis增强工具包,用于简化CRUD操作。该工具包为MyBatis提供了一些高效,有用,即用的功能,使用它可以有效地节省您的开发时间。 Mybatis-plus特征: 与MyBatis完全兼容 启动时自动配置 开箱即用的用于操作数据库的界面 强大而灵活的条件包装器 生成主键的多种策略 Lambda样式的API 全能和高度可定制的代码生成器 自动分页操作 SQL注入防御 支持活动记录 支持可插拔的自定义界面 内置许多有用的扩展 Mybatis-plus功能: 1、单表CURD(简单 + 批量)操作,自动完成(支持 like 比较等查询)。 2、分页插件,Count查询自动或自定义SQL查询。 3、Spring根据不同环境加载不同配置支持(支持typeAliasesPackage通配符扫描)。 【自动生成Entity  Mapper  Service文件】 Mybatis-plus更新日志: v3.4.3 增加瀚高数据库支持 增加注解 Order By 支持默认排序 Wrapper exists notExists orderBy groupBy 支持参数绑定 Wrapper 支持 setParamAlias 其它优化 优化 KeyGenerator 支持多实现多数据源注入 增强 ServiceImpl 泛型推断,解决多继承与代理问题 新增 PageDto 用于微服务对象传输序列化 新增 Page 提供静态 of 构造方式 增加代理 MethodHandleProxies 对 lambda 调试支持 调整 ActiveRecord 日志对象初始化 调整 ActiveRecord 模式 Model 类开发 pkVal 方法外部可用 删除标记过时代码 优化枚举值获取方式 分页 count 安全处理 Sequence 方法支持重写支持 升级 Mybatis 3.5.7 修复自动配置 lazy-initialization 无属性提示 修复 mysql on duplicate key update 字段名判断为表名问题 修复 lambda 条件 npe 异常 重构 lambda 信息提取方法 获取 lambda 信息不在序列化 合并 gitee pulls/ 141 fixed github issues/3208 3016 fixed github issues/3482 数据权限处理器支持 union all 调整事务未启用打印提示信息 单元测试优化相关依赖升级
在使用maven的mybatis-generator-maven-plugin插件自动生成实体映射文件时,我们首先需要在maven的pom.xml文件中配置插件。 在<build>标签下,添加如下代码: ``` <plugins> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.4.0</version> <dependencies> <!-- 添加数据库驱动依赖 --> </dependencies> <configuration> <verbose>true</verbose> <overwrite>true</overwrite> </configuration> </plugin> </plugins> ``` 接下来,在项目的根目录下执行以下命令生成实体映射文件: ``` mvn mybatis-generator:generate ``` 执行完毕后,插件会根据配置信息,在项目的src/main/java目录下生成对应的实体类、mapper接口和xml映射文件。 在配置插件时,可以设置数据库连接信息、需要生成的表名、生成的实体类和映射文件的位置等。具体的配置信息可以参考官方文档。 生成的实体类对应数据库中的表结构,各个字段通过对应的get和set方法来访问。生成的mapper接口定义了对应的数据库操作方法,通过调用这些方法可以对数据库进行增删改查操作。生成的xml映射文件定义了实体类和数据库表之间的映射关系,通过该文件可以实现对象和表的相互转换。 通过使用maven的mybatis-generator-maven-plugin插件,我们可以简化开发人员编写实体映射文件的工作,提高开发效率和代码质量。同时,插件的配置灵活多样,可以根据项目的实际需求进行定制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值