Mybatis TypeHandler 小计

在公司中,因为需要多数据库部分字段做加。 想到一种思路,可以在数据字段插入数据库之前,转化成密文。这样就可以做到应用层无感知处理数据加密问题了。 当然如果需要做到正在安全的


<!--结果集 -->
<result column="personPhone" property="personPhone" jdbcType="VARCHAR"
			typeHandler="com.hjb.learning.mybatis.type.MyTypeHandler" />
<!--更新、插入类 -->
#{personPhone,com.hjb.learning.mybatis.type.MyTypeHandler},
personPhone = #{personPhone,com.hjb.learning.mybatis.type.MyTypeHandler},

话,加密的token需要严格管控或者配置在服务器上只有部分小伙伴可以看到。这个是另外一个话题了。今天就聊一聊如何利用mybatis TypeHandler 实现加密解密处理。

1. 什么是typeHandler?

根据官方介绍https://mybatis.org/mybatis-3/zh/configuration.html#typeHandlers

  官方的话, 可能不太好理解。说的通透一点, typeHandler 其实就是转换数据库对象类型和java对象类型的一个转换器。

2. 已经了解了什么是TypeHandler了, 那么怎么使用呢?

其实官方也提供了对应的案例。我这边不适用官方的案例。

    1). 继承实现BaseTypeHandler,如下:


public class MyTypeHandler extends BaseTypeHandler<String> {
	@Override
	public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
			throws SQLException {
		// 设置 String 类型的参数的时候调用,Java类型到JDBC类型
		// 注意只有在字段上添加typeHandler属性才会生效
		// insertBlog name字段
		System.out.println("---------------setNonNullParameter1:" + parameter);
		ps.setString(i, parameter);
	}

	@Override
	public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
		// 根据列名获取 String 类型的参数的时候调用,JDBC类型到java类型
		// 注意只有在字段上添加typeHandler属性才会生效
		System.out.println("---------------getNullableResult1:" + columnName);
		return rs.getString(columnName);
	}

	@Override
	public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
		// 根据下标获取 String 类型的参数的时候调用
		System.out.println("---------------getNullableResult2:" + columnIndex);
		return rs.getString(columnIndex);
	}

	@Override
	public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
		System.out.println("---------------getNullableResult3:");
		return cs.getString(columnIndex);
	}
}

  2). mybatis-config.xml 填写typeHandler 相关的配置。 比如上述类,需要注意是类全路径

  <typeHandlers>
        <typeHandler handler="com.hjb.learning.mybatis.type.MyTypeHandler"></typeHandler>
    </typeHandlers>

  3)在真正使用的时候,在官方定义明确说明了,一个是在参数设置阶段,另外一个是在返回值解析阶段;分别对应往数据库写和从数据库读2个操作。 针对这2个场景分别说明:


<!--结果集 -->
<result column="personPhone" property="personPhone" jdbcType="VARCHAR"
			typeHandler="com.hjb.learning.mybatis.type.MyTypeHandler" />
<!--更新、插入类 -->
#{personPhone,com.hjb.learning.mybatis.type.MyTypeHandler},
personPhone = #{personPhone,com.hjb.learning.mybatis.type.MyTypeHandler},

经过上面3个步骤,基本的的typeHandler 使用应该不会有太大问题了。

当然主逻辑是写MyTypeHandler类里面。

 

3. 既然已经知道了如何使用了,那么该功能是如何实现的内?

  抓住2个点:1. 设置参数的时候 ; 2 返回值解析的时候

      就拿第一点设置参数的时候来来说明一下,这个怎么处理的。首选找到入口, mybatis 在什么时候设置参数?mybatis所有的信息都是从SQL配置文件搞起,typeHandler 也是其中一段文本, 那么必然需要解析这个属性。

主题思路如下:

   1. SQLMapper文件里面解析出typeHandler 属性的对象,并保存到ParameterMapping

    2. 在DefaultParameterHandler类的setParameters方法中,根据之前设置到的ParameterMapping,获取对应的typeHandler,并调用typehandler的setParameter方法。

就从解析SQL文本开始,可以找到解析类:SqlSourceBuilder。启用每一个#{}表达式都会进行解析,并且传递对应的参数类型

比如:#{vvv,jdbcType=Varchar}, #{vvv}, 一种是String,另外一种默认是Object(这个最终还是会适配对应的类型)

从代码里面,参数解析代码动作组要由内部类ParameterMappingTokenHandler实现。最终会调用到:

buildParameterMapping 方法比较关键, 这个方法实现了,java参数到SQL JDBC参数的转换过程。

这个方法有2出逻辑跟typeHandler相关。

 1. 

 

2. javaType 就是上一块代码得到的parameterType,下面这个代码的意思是: 如果存在typeHandler属性,那就解析,并存入builder 构造者中。

3. 解析TypeHandler .可以看到最核心的逻辑是, typeHandler 都是typeHandlerRegistry这类产生的。

    4. 那么我们需要看下, 这个typeHandlerRegistry 到底是什么?

通过搜索发现,这个TypeHandlerRegistry,配置在Configuration里面,也就是配置文件级别全局唯一的,并且是直接new产生的。

可以发现这个类,内部定义了很多默认的java 和JDBC的映射

并且有一溜的register方法。

其实Mybatis 在解析mybatis-config.xml的时候会将其中的typehandlers属性,解析出来,并且保存在这个TypeHandlerRegistry的

allTypeHandlersMap对象里面。当然同时也可以通过注解的方式注册进来。

再来看之前的 typeHandlerRegistry.getMappingTypeHandler(typeHandlerType);到底是怎么写的。

还有 handler = typeHandlerRegistry.getInstance(javaType, typeHandlerType); 可以发现其实他只是使用了,反射实例化对象

通过以上分析,大约知道了, typehandler对象是怎么解析了,然后保存在MapperStatment里面的。

第二步: 设置参数

DefaultParameterHandler类的实现如下:

 

以上是对设置参数环节的一些理解。整个过程,其实还算比较简单的。

核心的思想就是JAVA对象类型和JDBC对象类型转换过程中,留了一些钩子方法,给广大开发处理

 

对应返回值的解析过程,这边就不说了, 大体过程雷同,有兴趣的小伙伴自己研究一下吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值