上代码:

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. PAT甲级 1120. Friend Numbers (20)

    1120. Friend Numbers (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Two in ...

  2. HDU2159_二维完全背包问题

    HDU2159_二维完全背包问题 输入有:经验,忍耐度,怪物种数,限制杀怪数 每一种怪物对应获得的经验值和消耗的耐久值 输出:剩下的最大忍耐度 限制:忍耐度,杀怪个数 在这里把忍耐度看成背包的容量,杀 ...

  3. bootstrap1.3

    <html>   <head>   <meta charset="UTF-8">   <title></title>   ...

  4. linux查看RAID信息

    linux查看RAID信息 发表于2013 年 12 月 22 日 RAID分为软RAID和硬RAID 软RAID查看 cat /proc/mdstat 硬RAID查看 在启动画面进raid卡查看 I ...

  5. (原创)c++中的类型擦除

    c++11 boost技术交流群:296561497,欢迎大家来交流技术. 关于类型擦除,可能很多人都不清楚,不知道类型擦除是干啥的,为什么需要类型擦除.有必要做个说明,类型擦除就是将原有类型消除或者 ...

  6. Android-Kotlin-枚举enum

    案例一 星期: 星期的枚举:enum class 类名 {} package cn.kotlin.kotlin_oop09 /** * 定义星期的枚举类 */ enum class MyEnumera ...

  7. Maven的阿里云镜像

    打开“Maven安装目录/conf/settings.xml”文件,找到<mirrors>节点,添加: <mirror> <id>nexus-aliyun</ ...

  8. Spark技术的总结 以及同storm,Flink技术的对比

    spark总结 1.Spark的特点: 高可伸缩性 高容错 基于内存计算 支持多种语言:java,scala,python,R 高质量的算法,比MapReduce快100倍 多种调度引擎:可以运行于Y ...

  9. ASP.NET SignalR Troubeshooting

    method could not be resolved 场景: Javascript客户端不生成代理,调用服务端方法. 按照官网文档的用法: contosoChatHubProxy.invoke(' ...

  10. [UWP开发] 在低版本中使用亚克力刷以及部分高版本控件

    写于2018.10.3 仅在我的PC(17763)和WP(Limia 950 XL 15254)上测试过 微软在build 16299中引入了亚克力刷,但是Win10m并没有活那么久,lumia手机在 ...