上代码:

package tk.mybatis.plugin;

import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry; import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.PreparedStatement;
import java.util.*; /**
* JdbcTypeInterceptor - 运行时自动添加 jdbcType 属性
*/
@Intercepts({
@Signature(type = ParameterHandler.class, method = "setParameters", args = {PreparedStatement.class})
})
public class JdbcTypeInterceptor implements Interceptor { private static Set<String> methodSet = new HashSet<>();
private static Map<Class<?>, JdbcType> typeMap = new HashMap<>();
private static final Field mappedStatementField;
private static final Field boundSqlField; static {
try {
mappedStatementField = DefaultParameterHandler.class.getDeclaredField("mappedStatement");
mappedStatementField.setAccessible(true); } catch (NoSuchFieldException e) {
throw new RuntimeException("获取 DefaultParameterHandler 字段 mappedStatement 时出错", e);
}
try {
boundSqlField = DefaultParameterHandler.class.getDeclaredField("boundSql");
boundSqlField.setAccessible(true);
} catch (NoSuchFieldException e) {
throw new RuntimeException("获取 DefaultParameterHandler 字段 boundSql 时出错", e);
}
//设置默认的方法,是用 Mapper 所有方法
Method[] methods = tk.mybatis.mapper.common.Mapper.class.getMethods();
for (Method method : methods) {
methodSet.add(method.getName());
}
//设置默认的类型转换,参考 TypeHandlerRegistry
register(Boolean.class, JdbcType.BOOLEAN);
register(boolean.class, JdbcType.BOOLEAN); register(Byte.class, JdbcType.TINYINT);
register(byte.class, JdbcType.TINYINT); register(Short.class, JdbcType.SMALLINT);
register(short.class, JdbcType.SMALLINT); register(Integer.class, JdbcType.INTEGER);
register(int.class, JdbcType.INTEGER); register(Long.class, JdbcType.BIGINT);
register(long.class, JdbcType.BIGINT); register(Float.class, JdbcType.FLOAT);
register(float.class, JdbcType.FLOAT); register(Double.class, JdbcType.DOUBLE);
register(double.class, JdbcType.DOUBLE); register(String.class, JdbcType.VARCHAR); register(BigDecimal.class, JdbcType.DECIMAL);
register(BigInteger.class, JdbcType.DECIMAL); register(Byte[].class, JdbcType.BLOB);
register(byte[].class, JdbcType.BLOB); register(Date.class, JdbcType.DATE);
register(java.sql.Date.class, JdbcType.DATE);
register(java.sql.Time.class, JdbcType.TIME);
register(java.sql.Timestamp.class, JdbcType.TIMESTAMP); register(Character.class, JdbcType.CHAR);
register(char.class, JdbcType.CHAR);
} @Override
public Object intercept(Invocation invocation) throws Throwable {
//这里不考虑有多个基于该方法插件时的情况
Object handler = invocation.getTarget();
MappedStatement mappedStatement = (MappedStatement) mappedStatementField.get(handler);
//一旦配置了 methods,就只对配置的方法进行处理
if (handler instanceof DefaultParameterHandler) {
if (methodSet.size() > 0) {
String msId = mappedStatement.getId();
String methodName = msId.substring(msId.lastIndexOf(".") + 1);
if (!methodSet.contains(methodName)) {
return invocation.proceed();
}
}
//获取基本变量信息
BoundSql boundSql = (BoundSql) boundSqlField.get(handler);
Object parameterObject = ((DefaultParameterHandler) handler).getParameterObject();
Configuration configuration = mappedStatement.getConfiguration();
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
PreparedStatement ps = (PreparedStatement) invocation.getArgs()[0];
//原 DefaultParameterHandler 逻辑
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings != null) {
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
TypeHandler typeHandler = parameterMapping.getTypeHandler();
JdbcType jdbcType = parameterMapping.getJdbcType();
if (value == null && jdbcType == null) {
if (parameterMapping.getJavaType() != null && typeMap.containsKey(parameterMapping.getJavaType())) {
jdbcType = typeMap.get(parameterMapping.getJavaType());
} else {
jdbcType = configuration.getJdbcTypeForNull();
}
}
typeHandler.setParameter(ps, i + 1, value, jdbcType);
}
}
}
return null;
}
return invocation.proceed();
} @Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
} private boolean isNotEmpty(String str) {
return str != null && str.length() > 0;
} @Override
public void setProperties(Properties properties) {
String methodStr = properties.getProperty("methods");
if (isNotEmpty(methodStr)) {
//处理所有方法
if (methodStr.equalsIgnoreCase("ALL")) {
methodSet.clear();
} else {
String[] methods = methodStr.split(",");
for (String method : methods) {
methodSet.add(method);
}
}
}
//手动配置
String typeMapStr = properties.getProperty("typeMaps");
if (isNotEmpty(typeMapStr)) {
String[] typeMaps = typeMapStr.split(",");
for (String typeMap : typeMaps) {
String[] kvs = typeMap.split(":");
if (kvs.length == 2) {
register(kvs[0], kvs[1]);
}
}
}
} public static void register(String type, String jdbcType) {
try {
typeMap.put(Class.forName(type), JdbcType.valueOf(jdbcType));
} catch (ClassNotFoundException e) {
throw new RuntimeException("配置 typeMaps 时出错!", e);
}
} public static void register(Class<?> type, JdbcType jdbcType) {
typeMap.put(type, jdbcType);
}
}

在springboot中使用:

    @Bean
public Interceptor getInterceptor(){
return new JdbcTypeInterceptor();
}

它的好处,就是在运行mybatis动态sql的时候给属性添加jdbcType

mybatis jdbctype参考:https://www.cnblogs.com/pianai-shu/p/6349183.html

mybatis JdbcTypeInterceptor - 运行时自动添加 jdbcType 属性的更多相关文章

  1. (转载)让XCode运行时自动更新资源

    转自http://goldlion.blog.51cto.com/4127613/1351616 用过XCode的人都知道,XCode有一个臭名昭著的bug——除非你修改了源代码造成了重新编译,否则游 ...

  2. iOS开发——运行时OC篇&使用运行时获取系统的属性:使用自己的手势修改系统自带的手势

    使用运行时获取系统的属性:使用自己的手势修改系统自带的手势 有的时候我需要实现一个功能,但是没有想到很好的方法或者想到了方法只是那个方法实现起来太麻烦,一或者确实为了装逼,我们就会想到iOS开发中最牛 ...

  3. Visual studio 创建文件时自动添加备注

    Visual studio 创建文件时自动添加备注 描述 要求每回添加一个类,普通类或单元测试类文件头自动添加备注, 比如:Copyright, FileName, Author and so on. ...

  4. SpringBoot运行时动态添加数据源

    此方案适用于解决springboot项目运行时动态添加数据源,非静态切换多数据源!!! 一.多数据源应用场景: 1.配置文件配置多数据源,如默认数据源:master,数据源1:salve1...,运行 ...

  5. WordPress发布文章/页面时自动添加默认的自定义字段

    如果你每篇文章或页面都需要插入同一个自定义字段和值,可以考虑在WordPress发布文章/页面时,自动添加默认的自定义字段.将下面的代码添加到当前主题的 functions.php 即可: 1 2 3 ...

  6. swift3.0 运行时获取类的属性

    //定义Person类 class Person: NSObject { var name: String? //注意这里基本数据类型我定义的是必选属性 var age: Int = override ...

  7. Pycharm新建文件时自动添加基础信息

    位置:File->settings->Editor->File and Code Templates->Python Script 添加以下代码: #!/usr/bin/env ...

  8. vs install 安装时自动添加注册表

    思路:使用自定义 解决方案添加类库项目 添加安装程序类 随后右键查看代码 在构造函数添加事件 同时完成这个事件,在此事件中根据需要添加我们需要的内容,此处为添加注册表,并根据安装目录添加url pro ...

  9. 蚂蚁分类信息商家发布文章、商品外链及远程图片自动添加nofollow属性

    蚂蚁商户发布文章.商品是可以添加外链或者直接用外部图片,但是这对分类网站运营不利. 所以要对外链进行过滤,演示网站保洁,蚂蚁分类的源码. 下面就说下怎么处理自动给外链自动加上nofollow属性. 1 ...

随机推荐

  1. C#-VS异常处理

    VS异常处理 常规 try     可能会产生异常的代码,当一行产生异常,这行下面的代码不执行,转到catch开始执行 catch(system.Exception e)      e.message ...

  2. activeMq之hello(java)

    消息队列activeMq,   节省响应时间,解决了第三方响应时间长的问题让其他客户可以继续访问, 安装activeMq apache-activemq-5.14.0-bin\apache-activ ...

  3. 20155326 2016-2017-2 《Java程序设计》第7周学习总结

    20155326 2016-2017-2 <Java程序设计>第7周学习总结 教材学习内容总结 Lambda (1)如果使用JDK8的话,可以使用Lambda特性去除重复的信息. (2)在 ...

  4. js五道经典练习题--第三道实现购物车功能

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...

  5. 二分图匹配-HK算法

    先把代码贴上,其他南京回来再补了.. #include <cstdio> #include <cstdlib> #include <cstring> #includ ...

  6. linux 查看、关闭 ssh pts/n登录的用户

    1.查看登录用户: [root@TiaoBan- bin]# w :: up days, :, users, load average: 1.90, 1.75, 1.84 USER TTY FROM ...

  7. RPC、RMI、SOAP、WSDL的区别详解

    RPC与RMI的区别============================================================================RPC:(Remote Pr ...

  8. .net图表之ECharts随笔03-热力地图

    基于01和02 要得到如图所示的热力地图(我从NuGet上下载的包没有heatmap.js文件,没法直接搞热力图,只好暂时先搞着地图.后面尽量搞一下),一般要设置四个参数——title.tooltip ...

  9. Strust2总结

    1. JavaEE软件三层结构和MVC的区别? JavaEE软件三层机构是由sun公司提供JavaEE开发规范的:Web层(表现层).业务逻辑层.数据持久层.[其中WEB层会使用前端控制器模式] MV ...

  10. 【文文殿下】[AH2017/HNOI2017]礼物

    题解 二项式展开,然后暴力FFT就好了.会发现有一个卷积与c无关,我们找一个最小的项就行了. Tips:记得要倍长其中一个数组,防止FFT出锅 代码如下: #include<bits/stdc+ ...