类型处理器(typeHandlers)

MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时, 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型。
你可以重写已有的类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。 具体做法为:实现 org.apache.ibatis.type.TypeHandler 接口, 或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler, 并且可以(可选地)将它映射到一个 JDBC 类型。比如:

// @MappedTypes注解中的类代表此转换器可以自动转换为的java对象,@MappedJdbcTypes注解中设置的是对应的jdbctype,mysql的json对象对应的jdbctype为VARCHAR。
@MappedTypes(value = {JSONObject.class, MyAlarmTemplate.class})
@MappedJdbcTypes(value = {JdbcType.VARCHAR}, includeNullJdbcType = true)
public class GenericTypeHandler<T extends Object> extends BaseTypeHandler<T> {private Class<T> clazz;public GenericTypeHandler(Class<T> clazz) {if (clazz == null) throw new IllegalArgumentException("Type argument cannot be null");this.clazz = clazz;}/*** 设置非空参数* @param ps* @param i* @param parameter* @param jdbcType* @throws SQLException*/@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {ps.setString(i, JSON.toJSONString(parameter));}/*** 根据列名,获取可以为空的结果* @param rs* @param columnName* @return* @throws SQLException*/@Overridepublic T getNullableResult(ResultSet rs, String columnName) throws SQLException {String sqlJson = rs.getString(columnName);if (null != sqlJson) {return JSONObject.parseObject(sqlJson, clazz);}return null;}/*** 根据列索引,获取可以为空的结果* @param rs* @param columnIndex* @return* @throws SQLException*/@Overridepublic T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {String sqlJson = rs.getString(columnIndex);if (null != sqlJson) {return JSONObject.parseObject(sqlJson, clazz);}return null;}@Overridepublic T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {String sqlJson = cs.getString(columnIndex);if (null != sqlJson) {return JSONObject.parseObject(sqlJson, clazz);}return null;}
}

使用上述的类型处理器将会覆盖已有的处理 Java MyAlarmTemplate类型的属性以及 VARCHAR 类型的参数和结果的类型处理器。 要注意 MyBatis 不会通过检测数据库元信息来决定使用哪种类型,所以你必须在参数和结果映射中指明字段是 VARCHAR 类型, 以使其能够绑定到正确的类型处理器上。这是因为 MyBatis 直到语句被执行时才清楚数据类型。

通过类型处理器的泛型,MyBatis 可以得知该类型处理器处理的 Java 类型,不过这种行为可以通过两种方法改变:

1.在类型处理器的配置元素(typeHandler 元素)上增加一个 javaType 属性(比如:javaType=“String”);
在类型处理器的类上增加一个 @MappedTypes 注解指定与其关联的 Java 类型列表。 如果在 javaType 属性中也同时指定,则注解上的配置将被忽略。
2.可以通过两种方式来指定关联的 JDBC 类型:
在类型处理器的配置元素上增加一个 jdbcType 属性(比如:jdbcType=“VARCHAR”);
在类型处理器的类上增加一个 @MappedJdbcTypes 注解指定与其关联的 JDBC 类型列表。 如果在 jdbcType 属性中也同时指定,则注解上的配置将被忽略。
也就是说配置文件中的优先级大于注解里的优先级。
上面展示了用注解实现类型处理器的代码。下面展示在配置里加配置如何实现类型处理器

<resultMap id="baseResult" type="com.muyuan.platform.alarm.admin.api.model.dto.manager.MyAlarmAlarmTemplateInfoDTO" autoMapping="true"><id property="id" column="id"/><result property="template" column="template" typeHandler="com.muyuan.platform.alarm.admin.biz.handler.GenericTypeHandler" javaType="com.muyuan.platform.alarm.admin.api.model.dto.manager.MyAlarmTemplate" jdbcType="VARCHAR"/></resultMap>

注意:
当在 ResultMap 中决定使用哪种类型处理器时,此时 Java 类型是已知的(从结果类型中获得),但是 JDBC 类型是未知的。 因此 Mybatis 使用 javaType=[Java 类型], jdbcType=null 的组合来选择一个类型处理器。 这意味着使用 @MappedJdbcTypes 注解可以限制类型处理器的作用范围,并且可以确保,除非显式地设置,否则类型处理器在 ResultMap 中将不会生效。 如果希望能在 ResultMap 中隐式地使用类型处理器,那么设置 @MappedJdbcTypes 注解的 includeNullJdbcType=true 即可。 然而从 Mybatis 3.4.0 开始,如果某个 Java 类型只有一个注册的类型处理器,即使没有设置 includeNullJdbcType=true,那么这个类型处理器也会是 ResultMap 使用 Java 类型时的默认处理器。

你可以创建能够处理多个类的泛型类型处理器。为了使用泛型类型处理器, 需要增加一个接受该类的 class 作为参数的构造器,这样 MyBatis 会在构造一个类型处理器实例的时候传入一个具体的类。

补充:如果看了文档也不太清除,可以阅读自定义类型处理器参考官方文档

https://mybatis.org/mybatis-3/zh/configuration.html#typeHandlers

在mybatis里如何自定义类型处理器相关推荐

  1. MyBatis核心源码剖析(SqlSession XML解析 Mapper executor SQL执行过程 自定义类型处理器 缓存 日志)

    MyBatis核心源码剖析 MyBatis核心源码剖析 1 MyBatis源码概述 1.1 为什么要看MyBatis框架的源码 1.2 如何深入学习MyBatis源码 1.3 源码分析的5大原则 2 ...

  2. MyBatis自定义类型处理器 TypeHandler

    在项目开发中经常会遇到一个问题: 当我们在javabean中自定义了枚举类型或者其它某个类型,但是在数据库中存储时往往需要转换成数据库对应的类型,并且在从数据库中取出来时也需要将数据库类型转换为jav ...

  3. MyBatis自定义类型处理器(typeHandler)

    MyBatis自定义类型处理器(typeHandler) 我们执行sql语句通过PreparedStatement语句实现,PreparedStatement会设置?值,类型处理器帮PreparedS ...

  4. 自定义类型处理器的应用

    问题描述: 一个JSON字符串在转对象的时候报JSON解析异常的错误,我仔细看了一下错误堆栈,是枚举导致的数组越界问题. [{"fee":0,"amount": ...

  5. QT学习杂项(1)--在connet函数里使用自定义类型

     在connet函数里使用自定义类型时,需要在类的构造函数里注册一下,否则会提示XXXType未知大小. eg: 1.先在构造函数里注册:qRegisterMetaType<QVector& ...

  6. TypeScript里的自定义类型用法

    新建一个index.ts: type NumGenerator = (input: number) => number;function myFunc(numGenerator: NumGene ...

  7. 【Mybatis】类型处理器TypeHandler的作用与自定义

    一.什么是类型处理器 1.类型处理器(TypeHandler) MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时,都会用类型处理器将获取到的值以合 ...

  8. mybatis-plus/mybatis的组件们——拦截器、字段填充器、类型处理器、表名替换、SqlInjector(联合主键处理)

    最近有个练手的小例子,大概就是配置两个数据源,从一个数据源读取数据写到另一个数据源,虽然最后做了出来,但是不支持事务...就当是对mybatis-plus/mybatis组件使用方式的记录吧,本次例子 ...

  9. desc 枚举类型id_想让代码更优雅?Mybatis类型处理器了解一下!

    明确需求 在设计之初,sys_role表的enabled字段有2个可选值,其中0 代表禁用,1代表启用,而且实体类中我们使用的是Interger类型: 源码展示 /** * 有效标志 */ priva ...

最新文章

  1. Kinect+OpenNI学习笔记之12(简单手势所表示的数字的识别)
  2. 【转贴】C#中事件处理的个人体会
  3. 【SRM-05 B】无题?
  4. [CareerCup] 4.7 Lowest Common Ancestor of a Binary Search Tree 二叉树的最小共同父节点
  5. 论文浅尝 | Reinforcement Learning for Relation Classification
  6. Linux安装Flash脚本,Linux(CentOS)下的Shockwave Flash shell一键更新脚本
  7. 【云速建站】会员注册弹窗添加及设置
  8. 机器学习监督学习之分类算法---朴素贝叶斯代码实践
  9. mac计算机如何调出来,新买的Mac电脑怎么设置?需完成这6步操作
  10. WPF-遍历页面所有TextBox做数据校验
  11. 计算机维修主板,电脑维修|干货收好!自己就能修主板
  12. 电子计算机与电子计算器,电子计算机与计算器的区别
  13. PCHunter_32X64_2022_03最新版
  14. SpringCloud系列——Eureka中Region和Zone概念介绍
  15. 基于OpenCV实现二维码发现与定位
  16. 【小技巧】一种简单的办法在verilog中处理小数运算
  17. 又学一招——Chrome 插件安装技巧
  18. 流媒体-RTMP协议-rtmpdump-flv封装解析(一)
  19. Accumulation Degree -换根dp
  20. Blink SQL DDL语句概述

热门文章

  1. CString类常用方法----TrimLeft(),TrimRight()
  2. Android 12应用适配指南
  3. 计算机毕业设计Python+uniapp+安卓养老管理APP(WEB+APP+LW)
  4. 优先队列——PriorityQueue详解
  5. eWebEditor V7.3 for asp版本编辑器带后的破解码版本,新增加防止图片木马上传
  6. 雪城大学 计算机专业,雪城大学计算机科学专业.pdf
  7. 网卡多队列,中断配置
  8. seajs.use 用法
  9. ABAP 后台执行程序
  10. Matlab质心算法