Mybatis 插件实现动态设置参数
原文地址:Mybatis 插件实现动态设置参数
博客地址:http://www.extlight.com
一、背景
笔者在搭建架构时,通常会利用泛型对 dao 层 和 service 层公共的代码(增删改)进行抽取,但是遇到一个尴尬的问题,就是实体类中的时间设置。
解决办法有很多,简单的方法就是在 web 层接收实体类参数后直接设置时间即可。但是,web 层理论上只是调用 service 层代码而已,设置时间的操作应该放在 service 层来实现,且设置时间又是一个简单的、重复性的操作,因此在网上查阅了一些资料,个人感觉比较友好的方式就是使用 Mybatis 插件。
本文介绍使用 Mybatis 插件动态设置参数。
二、Mybatis 插件简单介绍
Mybatis 提供 Interceptor 接口,配合 @Intercepts 注解可以拦截如下 4 个对象的方法调用:
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)
其关系如下图:

解释:
Executor 是 Mybatis 的内部执行器,它负责调用 StatementHandler 操作数据库,并把结果集通过 ResultSetHandler 进行自动映射,另外,它还处理了二级缓存的操作。
StatementHandler 是 Mybatis 直接和数据库执行 sql 脚本的对象,另外,它也实现了 Mybatis 的一级缓存。
ParameterHandler 是 Mybatis 实现 sql 入参设置的对象。
ResultSetHandler 是 Mybatis 把 ResultSet 集合映射成 POJO 的接口对象。
本篇不陈述 Mybatis 的内部原理,感兴趣的读取请自行查阅相关资料。
三、案例演示
案例主要演示如何编写 Mybatis 自定义插件来实现动态设置时间参数,解决上文提到的问题。
3.1 自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface CreateTime {
String value() default "";
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface UpdateTime {
String value() default "";
}
将两个注解添加到实体类的 Date 类型成员变量上。
@Data
public class Category {
private Integer id;
private String name;
private String descr;
@CreateTime
private Date createTime;
@UpdateTime
private Date updateTime;
}
3.2 自定义插件
/**
* 自定义 Mybatis 插件,自动设置 createTime 和 updatTime 的值。
* 拦截 update 操作(添加和修改)
*/
@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class CustomInterceptor implements Interceptor {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public Object intercept(Invocation invocation) throws Throwable {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
// 获取 SQL 命令
SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
// 获取参数
Object parameter = invocation.getArgs()[1];
// 获取私有成员变量
Field[] declaredFields = parameter.getClass().getDeclaredFields();
for (Field field : declaredFields) {
if (field.getAnnotation(CreateTime.class) != null) {
if (SqlCommandType.INSERT.equals(sqlCommandType)) { // insert 语句插入 createTime
field.setAccessible(true);
field.set(parameter, new Date());
}
}
if (field.getAnnotation(UpdateTime.class) != null) { // insert 或 update 语句插入 updateTime
if (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)) {
field.setAccessible(true);
field.set(parameter, new Date());
}
}
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
3.3 注册插件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 获取数据库自增主键值 -->
<setting name="useGeneratedKeys" value="true"/>
<!-- 使用列别名替换列名,默认为 true -->
<setting name="useColumnLabel" value="true"/>
<!-- 开启驼峰命名转换:Table(create_time) => Entity(createTime) -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<plugins>
<plugin interceptor="com.extlight.plugin.CustomInterceptor">
</plugin>
</plugins>
</configuration>
通过这三个步骤就解决问题了。
四、参考资料
Mybatis 插件实现动态设置参数的更多相关文章
- FlexSlider插件的详细设置参数 http://www.woothemes.com/flexslider/
http://www.woothemes.com/flexslider/ FlexSlider插件的详细设置参数 $(window).load(function() { $('.flexslider' ...
- Unity---DOTween插件学习(2)---设置参数、Ease曲线、回调函数、动画控制函数
目录 6.Set设置参数 7.Ease曲线 8.回调函数 9.动画控制函数 本文及系列参考于Andy老师的DOTween系列 欢迎大家关注Andy老师 6.Set设置参数 在Unity中添加一个Cub ...
- FlexSlider插件的详细设置参数
FlexSlider是一个非常出色的jQuery滑动切换插件,它支持所有主流浏览器,并有淡入淡出效果.适合所有初级和高级网页设计师使用.不过很多人都只是使用默认的参数,今天来说说具体的参数来给大家看看 ...
- postmain 通过函数动态设置参数
调用服务器的服务,其中有个参数是签名,签名需要计算,需要写一个本地函数. 下一步 pre-request Script 的代码如下: (function($) { if(!$.encoding) $. ...
- FlexSlider插件的详细设置参数 http://www.woothemes.com/flexslider/ -----幻灯片插件
$(window).load(function() { $('.flexslider').flexslider({ namespace: 'flex-', //控件的命名空间,会影响样式前缀 anim ...
- MyBATIS插件原理第一篇——技术基础(反射和JDK动态代理)(转)
在介绍MyBATIS插件原理前我们需要先学习一下一些基础的知识,否则我们是很难理解MyBATIS的运行原理和插件原理的. MyBATIS最主要的是反射和动态代理技术,让我们首先先熟悉它们. 1:Jav ...
- 为maven插件设置参数的三种方法
很多的maven插件都提供了丰富的可选参数,用户可以通过设置特定的参数值来控制maven插件的行为.设置插件参数的方法主要有三种,分别是命令行设置,POM文件中为插件设置全局参数和POM文件中为插件设 ...
- XgCalendar日历插件动态添加参数
在使用xgcalendar日历插件的时候,参数数组并非只有类型.显示时间.时区等这些参数,还可以根据extParam自定义参数扩展搜索条件,例如根据用户Id搜索不同用户的日历信息,需要将用户的Id存在 ...
- asp.net动态设置button的Text,Enabled属性,向后台传递参数
前台代码:根据后台传递过来的参数动态设置 <asp:Button ID="Button1" runat="server" CommandArgument= ...
随机推荐
- php时间戳函数mktime()
在项目开发中,偶尔会遇到跨周期.跨月的的时间操作.PHP为我们提供了一个很方便的函数->mktime,可以很简单的获取制定日期的时间戳了. mktime(hour,minute,second,m ...
- 20145204《Java程序设计》第3周学习总结
20145204<Java程序设计>第3周学习总结 教材学习内容总结 对象和类. Java有基本类型和类类型这两个类型系统.本章主要介绍类类型.定义类时用关键词class,利用类建立对象实 ...
- cuda8.0 出错:/usr/bin/ld: 找不到 -lGL【转】
本文转自:https://blog.csdn.net/u010159842/article/details/56833030 最近在学习深度学习,在搭建CUDA8.0的时候,出现一个非常不好的问题: ...
- openwrt下使用wget出现Failed to allocate uclient context
一.场景重现 root@OpenWrt:/# wget www.baidu.com Downloading 'www.baidu.com' Failed to allocate uclient con ...
- 解决com.mongodb.MongoException$CursorNotFound: cursor 0 not found on server
背景 经常需要执行脚本调用Java程序读取mongodb中数据,本来是转为后台进程.偶尔看看日志的简单任务.今天发现程序抛出异常“com.mongodb.MongoException$CursorNo ...
- p4c-bm安装
Generates the JSON configuration for the behavioral-model (bmv2).它是用来形成 行为模型BMV2 的 JSON配置 的. Importa ...
- springboot2 统一异常处理
统一异常处理,不需要在每一层上单独捕获异常,只需要关注业务的开发: 代码如下: @RestControllerAdvice @Slf4j public class GlobalExceptionHan ...
- [sql]java.sql.Types的具体对应值(jdbcType)
public final static int BIT = -7; public final static int TINYINT = -6; public final static int ...
- mongo 增删改查
1. use foobar2. show dbs3. show collections4. db.system.indexes.find()5. db.persons.find()6. db.pers ...
- express 调优的一个过程和心得,不错的文章
Netflix的软件工程师Yunong Xiao最近在公司的技术博客上写了一篇文章,分析了他所在的团队在将Netflix网站UI转移到Node.js上时遇到的延迟问题.在文章中他描述了找到问题根本原因 ...