β

06-13Mybatis 插件实现动态设置参数

Harries Blog™ 3 阅读

一、背景

笔者在搭建架构时,通常会利用泛型对 dao 层 和 service 层公共的 代码 (增删改)进行抽取,但是遇到一个尴尬的问题,就是实体类中的 时间 设置。

解决办法有很多,简单的方法就是在 web 层接收实体类 参数 后直接设置时间即可。但是,web 层理论上只是调用 service 层代码而已,设置时间的操作应该放在 service 层来实现,且设置时间又是一个简单的、重复性的操作,因此在网上查阅了一些资料,个人感觉比较友好的方式就是使用 Mybatis 插件

本文介绍使用 Mybatis 插件动态设置参数。

二、Mybatis 插件简单介绍

Mybatis 提供 Interceptor 接口,配合 @Intercepts 注解可以拦截如下 4 个对象的方法调用:

  1. Executor ( update , query, flush Statement s, commit, rollback, getTransaction, close, isClosed)
  2. ParameterHandler (getParameterObject, setParameters)
  3. ResultSet Handler (handleResultSets, handleOutputParameters)
  4. StatementHandler (prepare, parameterize, batch, update, query)

其关系如下图:

06-13Mybatis 插件实现动态设置参数

解释:

  1. Executor 是 Mybatis 的内部执行器,它负责调用 StatementHandler 操作 数据库 ,并把结果集通过 ResultSetHandler 进行自动映射,另外,它还处理了 二级缓存 的操作。

  2. StatementHandler 是 Mybatis 直接和 数据 库执行 sql 脚本的对象,另外,它也实现了 Mybatis 的 一级缓存

  3. ParameterHandler 是 Mybatis 实现 sql 入参设置的对象。

  4. ResultSetHandler 是 Mybatis 把 ResultSet 集合映射成 POJO 的接口对象。

本篇不陈述 Mybatis 的内部原理,感兴趣的读取请自行查阅相关资料。

三、案例演示

案例主要演示如何编写 Mybatis 自定义插件来实现动态设置时间参数,解决上文提到的问题。

3.1 自定义注解

  1. @Retention(RetentionPolicy.RUNTIME)
  2. @Target({ElementType.FIELD})
  3. public @interface CreateTime {
  4. String value () default "";
  5. @Retention(RetentionPolicy.RUNTIME)
  6. @Target({ElementType.FIELD})
  7. public @interface UpdateTime {
  8. String value() default "";

将两个注解添加到实体类的 Date 类型成员变量上。

  1. @Data
  2. public class Category {
  3. private Integer id ;
  4. private String name;
  5. private String descr;
  6. @CreateTime
  7. private Date createTime;
  8. @UpdateTime
  9. private Date updateTime;

3.2 自定义插件

  1. /**
  2. * 自定义 Mybatis 插件,自动设置 createTime 和 updatTime 的值。
  3. * 拦截 update 操作(添加和修改)
  4. */
  5. @Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
  6. public class CustomInterceptor implements Interceptor {
  7. private final Logger logger = LoggerFactory.getLogger(this.getClass());
  8. @Override
  9. public Object intercept(Invo cat ion invocation) throws Throwable {
  10. MappedStatement map pedStatement = (MappedStatement) invocation.getArgs()[0];
  11. // 获取 SQL 命令
  12. SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
  13. // 获取参数
  14. Object parameter = invocation.getArgs()[1];
  15. // 获取私有成员变量
  16. Field[] declaredFields = parameter.getClass().getDeclaredFields();
  17. for (Field field : declaredFields) {
  18. if (field.getAnnotation(CreateTime.class) != null) {
  19. if (SqlCommandType.INSERT. equals (sqlCommandType)) { // insert 语句插入 createTime
  20. field.setAccessible(true);
  21. field.set(parameter, new Date());
  22. if (field.getAnnotation(UpdateTime.class) != null) { // insert 或 update 语句插入 updateTime
  23. if (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)) {
  24. field.setAccessible(true);
  25. field.set(parameter, new Date());
  26. return invocation.proceed();
  27. @Override
  28. public Object plugin (Object tar get) {
  29. return Plugin.wrap(target, this);
  30. @Override
  31. public void setProperties(Properties properties) {

3.3 注册插件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-// mybatis .org//DTD Config 3.0//EN"
  4. " http ://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <configuration>
  6. <settings>
  7. <!– 获取数据库自增 主键值 –>
  8. <setting name="useGeneratedKeys" value="true"/>
  9. <!– 使用列别名替换列名,默认为 true –>
  10. <setting name="useColumnLabel" value="true"/>
  11. <!– 开启驼峰命名转换:Table(create_time) => Entity(createTime) –>
  12. <setting name="mapUnders core ToCamelCase" value="true"/>
  13. </settings>
  14. <plugins>
  15. <plugin interceptor="com.extlight.plugin.CustomInterceptor">
  16. </plugin>
  17. </plugins>
  18. </configuration>

通过这三个步骤就解决问题了。

四、参考资料

原文

https ://www.extlight.com/2018/06/13/Mybatis-插件实现动态设置参数/

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。 PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处: Harries Blog™ » 06-13Mybatis 插件实现动态设置参数

作者:Harries Blog™
追心中的海,逐世界的梦
原文地址:06-13Mybatis 插件实现动态设置参数, 感谢原作者分享。

发表评论