java sql结果写入csv文件_Mybatis TypeHandler(类型处理器)转换参数到SQL和转换SQL查询结果到Java类...

  1. TypeHandler介绍
  2. TypeHandler的实际运用
  3. TypeHandler作用原理

TypeHandler介绍

在预处理语句(PreparedStatement)中设置一个参数时,或者从结果集中取出一个值时, 都会用TypeHandler将获取的值以合适的方式设置到PreparedStatement,或者转换成Java类型。

可以重写TypeHandler或创建自己的TypeHandler来处理不支持的或非标准的类型。 具体做法为:实现org.apache.ibatis.type.TypeHandler接口, 或继承一个很便利的类org.apache.ibatis.type.BaseTypeHandler。

TypeHandler的实际运用

一般在项目中设计表结构的时候对于一些只有有限个值的字段,都会用数字类型来表示。例如表示考试的状态字段exam_status表类型会定义为tinyint,并且使用 1:未开始;2:待考试;3:考试中;4:已完成 来表示考试的不同状态。

那么对于类似这样的字段,如果我们在代码中直接使用Integer来表示的话,这个可读性和可维护性还是挺差的,所以一般都会定义一个枚举来表示,像这样:

public 

那么问题来了,如何才能使得数据库的数字类型的exam_status转换成ExamStatusEnum类呢?

方案一:每次使用手工转换,麻烦啰嗦,不可取

方案二:配置Mybatis,使得能够自动完成这个转换工作

为了使用方案二,来看下解决方案:

首先,这些枚举类需实现一个共同的接口,也就是EnumBase接口,里面有一个关键的静态方法codeOf,实现数字转换成特定枚举的功能,然后编写TypeHandler:

public 

我大概对EnumBaseTypeHandler类的几个方法做下说明:

  1. void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) 该方法为设置参数使用的转换方法,也就是转换参数到SQL
  2. E getNullableResult(ResultSet rs, String columnName) 该方法是拿到结果集后根据列名称处理结果,也就是将数据库的字段值转换为Java 的属性值
  3. E getNullableResult(ResultSet rs, int columnIndex) 该方法是拿到结果集后根据列序号处理结果,也就是将数据库的字段值转换为Java 的属性值
  4. E getNullableResult(CallableStatement cs, int columnIndex) 该方法是针对存储过程转换结果

最后,为了避免需要在Mybatis的xml配置文件为每个这样的枚举声明,类似这样:

0a3ede918183850001e597256df00e1d.png

这里就不再使用xml文件来做配置,所有配置信息使用Java代码来直接设置,这也是为了能够动态注册TypeHandler所必须要做的,主要关键就是这个Java配置:

@Bean
    

完成这些工作后就能让Mybatis自动将数据库表字段数字转换成Java Bean 的特定枚举类型字段。

TypeHandler作用原理

Mybatis有一个注册工厂为TypeHandlerRegistry的类,里面初始化了常见类型的转换器,例如我们看下String类型:

register

register 方法最终会调用到TypeHandlerRegistry的这个方法:

private 

TYPE_HANDLER_MAP的定义是这样的:

private 

里面就存放了Java类型对应的TypeHandler。

Mybatis执行转换时,是根据这个方法来获取TypeHandler的:

private 

从这里我们可以看出获取TypeHandler的顺序是:

  1. 根据Java字段类型+jdbc类型
  2. 根据Java字段类型
  3. 根据jdbc类型

我们的自定义枚举类型能起作用就是依据这里:

EnumBaseTypeHandler 

下面我们看下Mybatis如何使用TypeHandler实现参数设置到sql中和转换SQL查询结果到Java类的,以下面例子来讲解:

@Service

mapper文件是这样的:

<mapper 

跟踪Mybatis解析这个mapper xml文件的流程,可以看到最终所有parameter入参的Java参数都是使用这个方法来关联TypeHandler的,其中每条SQL的parameter入参都会解析成一个ParameterMapping对象:

private 

但这时候关联的都是UnknownTypeHandler,因为xml中字段并没指定JavaType和jdbcType属性,那么Java类型就会默认是Object类型(没指定parameterType属性,所以没法知道实际类型,只有等到运行时才能得到。因此只有指定parameterType属性,这里Mybatis才能相应的获取到实际Java类型),jdbc类型默认是null,所以关联到了UnknownTypeHandler

而resultMap的Java参数则是使用这个方法来关联TypeHandler的,其中resultMap元素会解析成一个ResultMapping对象:

private 

此时Mybatis根据type="org.javamaster.b2c.core.entity.MicrowebsiteExam"就会相应的获取到了实际Java类型并和具体的TypeHandler关联起来,例如examType属性就会和EnumBaseTypeHandler关联起来。

在执行这行代码时:

List

对于SQL参数的设置,跟踪源码执行流程,可以看到(只留下关键代码):

public 

我们看下UnknownTypeHandler的setParameter方法,参数如果不是null,最终是调用了自身的setNonNullParameter方法:

public 

所以获取真正的TypeHandler并设置SQL参数是这个方法完成的,这个resolveTypeHandler最终是调用到了我前面提到的TypeHandlerRegistry.getTypeHandler(javaType, jdbcType)方法。

对于转换SQL查询结果到Java类,跟踪源码执行流程,这个流程就复杂了很多,可以看到(只留下关键代码),是由DefaultResultSetHandler 来处理的:

public 

好,整个Mybatis的执行流程就分析完了,有兴趣的同学可以自己去实践下。

源码github地址:

jufeng98/java-master​github.com
4b09cd7530dba1cd4f9b4175125daef9.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值