点击蓝色“程序猿DD”关注我

回复“资源”获取独家整理的学习资料!

抛开使用场景谈技术都是耍流氓

1. 场景

日常java开发中经常有这种需求,用0或者1这些代码(不局限于数字)来表示某种状态。比如用0表示女性,用1来表示男性。而且写入数据库可能是一个标识,从数据库读取又还原为具体的说明。而且一般情况下为了更好理解或者消除魔法值,通常的处理方案是定义一个枚举,有些枚举是这样定义的:

那么通常很多人会这么入库(java伪代码)

读取的时候要么同样按照上面的再反向处理一次或者使用数据库sql语法case when来直接写入DTO

这种处理方式看起来不是很优雅。而且多了很多的判断和处理逻辑,和我们的业务并不是非常相关。所以我们可以选择更好的处理方式。

2. Mybatis中的TypeHandler

如果你ORM框架用的是Mybatis。那么将很容易通TypeHandler<T>接口解决这个问题。这是Mybatis提供的一个类型转换接口,将数据库的jdbc类型和java中的类型进行相互转换。接下来我们将一步一步地来研究这个接口。

2.1 TypeHandler

源码分析:

  • setParameter 方法 通过 传入的T类型写你自己的逻辑,选择调用 PreparedStatement 对象的某个set方法将数据写入数据库。此方法用来写库。

  • getResult(ResultSet rs, String columnName) 通过字段名来读库并转换为T类型。

  • getResult(ResultSet rs, int columnIndex) 通过字段索引来读库并转换为T类型。

  • getResult(CallableStatement cs, int columnIndex) 调用存储过程来获取结果并转换为T类型。

2.2 EnumOrdinalTypeHandler

我们发现TypeHandler有一个实现类EnumOrdinalTypeHandler。字面意思是可以通过枚举的序号来处理类型。

我们先不考虑setNull的情况。通过此方法我们发现确实存入的是枚举的顺序值(顺序从0开始),拿上面的例子来说 如果是GenderType.FEMALE是0,如果是GenderType.MALE是1,但是当GenderType.UNKNOWN时存入的是2。取的时候也是自然反向处理为具体的GenderType枚举。

2.3 EnumTypeHandler

我们还发现有另外一个枚举类型处理器。它的set方法是这样的:

我们不考虑jdbcType问题发现都是将Enum.name()的值写入数据库。拿上面的例子来说 如果是GenderType.FEMALE是FEMALE,如果是GenderType.MALE是MALE,但是当GenderType.UNKNOWN时存入的是UNKNOWN。读库是通过Enum.valueOf(Class<T> enumType,String name)来进行反转操作。

2.4 自定义TypeHandler

如果说我们的枚举类型或者说我们使用其他方式来处理类别转换怎么办?当然Mybatis不会帮你干这么具体的事情。需要你自己来实现了。我们还拿枚举作为例子,然后模仿上面的两种TypeHandler。还是拿开始的例子来说通常我个人比较喜欢这么定义枚举:

通过继承BaseTypeHandler实现该抽象类的3个钩子方法就行了:

TypeHandler 实现写好了,那么如何让其发挥作用呢?我们接着往下走。

2.5 TypeHandler的核心要点

TypeHandler作用是javaType和jdbcType相互转换。所以在声明一个TypeHandler的时候一定要明确该TypeHandler处理的这两种类型。这是必须要明确的原则。

MyBatis不会通过窥探数据库元信息来决定使用哪种JDBC类型,所以你必须在参数和结果映射中指明何种类型的字段,使其能够绑定到正确的类型处理器上。MyBatis直到语句被执行时才清楚数据类型。

通过上述例子中的@MappedJdbcTypes和@MappedTypes来进行绑定类型转换关系,也可以通过xml的typeHandler元素中的jdbcType或者javaType来指定。如果同时指定,xml的优先级要高。注意有可能你会覆盖内置的TypeHandler。所以自定义时一定要去了解Mybatis提供的一些默认处理器。避免对其他业务的影响。

使用自定义TypeHandler很重要的一个原则就是一定要声明JavaType和JdbcType。上面这些虽然比较生涩但是对于使用好TypeHandler非常重要。接下来我们来讲讲具体的配置。

2.6 免注册TypeHandler

我们这里只讲最常用xml中的配置,你可以举一反三:

  • 一种在resultMap元素中声明一般用来查询。一定要注意2.5中的一些原则。

  • 然后是在插入、更新语句中使用。它们都是相同的,这里只举一个插入例子。

如果注册了别名上面的都可以使用别名来减少冗长的全限定名。上面的好处就是不用在TypeHandlerRegistry中进行注册。

2.7 注册TypeHandler

在配置中声明注册TypeHandler,然后Mybatis根据两种类型会自动匹配。所以这里还是要强调2.5中的核心要点。

  • 如果你是xml配置需要在Configuration配置文件中的<typeHandlers>标签中进行声明式注册

  • javaConfig 方式 ,第一你可以通过SqlSessionFactory对象取到Configuration对象将typeHandler注册进去。如果你使用mybatis-spring组件,可以在SqlSessionFactoryBean的setTypeHandlersPackage方法中配置typeHandler的集中包路径,那么框架将会自动扫描并注册他们。springboot中对应的配置属性是mybatis.typeHandlersPackage。如果你注册了TypeHandler。在Mapper.xml中只需要声明jdbcType和javaType,无需再声明具体的typeHandler。Mybatis会自动通过jdbcType、javaType映射到具体注册的TypeHandler上去 。就像下面的例子:

3.总结

今天我们学习了mybatis开发中如何通过使用类型处理器进行类型的转换处理,如何处理枚举,如何自定义处理器并使用它。其实不仅仅局限于枚举。留给你自己去发现。相关的代码在我的码云仓库中:https://gitee.com/felord/mybatis-test.git

留言交流不过瘾?添加微信:zyc_enjoy

根据指引加入各种主题讨论群

每日一问

今日问题

一个岔路口分别通向诚实国和说谎国。来了两个人,已知一个是诚实国的,另一个是说谎国的。诚实国永远说实话,说谎国永远说谎话。现在你要去说谎国,但不知道应该走哪条路,需要问这两个人。请问应该怎么问?

(留言说说你的答案吧,明日推文公布答案)

昨日答案

点燃身前的草,由于风的作用,火会继续往前蔓延,烧过的地方就留下了不可燃的隔离区,人只需要待在这个被烧过的地方就不会被身后的大火烧到。

(昨日问题可在昨日推文的文末查看)

推荐阅读

  • Spring Cloud Alibaba 发布第一个正式版本,顺利完成孵化!

  • 用命令行在控制台里玩斗地主,试过没?

  • Spring Boot 面试的十个问题

  • Spring WebClient vs. RestTemplate

  • Apache Maven 最全教程,7000 字总结!

签到计划

活动介绍:自律到极致-人生才精致:第11期

活动奖励:《中台战略:中台建设与数字商业》

扫描下方二维码,查看本书详情

扫描下放二维码,签到参与

来星球聊聊技术人的斜杠生活

点一点“阅读原文”小惊喜在等你

玩转Mybatis中的类型转换器TypeHandler相关推荐

  1. Mybatis中的类型转换器

    无论是mybati是向数据库中存储数据还是将数据读取出来都需要涉及类型转换器. Mybatis再带的类型转换器:[部分] 自定义类型处理器 自定义类型转换器的解决方案: 重写已经有的类型转换器. 新建 ...

  2. oracle typehandler,Mybatis实现自定义的类型转换器TypeHandler

    此文其实是java操作Oracle类型XMLType总结二:使用Mybatis附带的一篇小结. Mybatis实现自定义的转换器,十分的简单,其主要步骤分为三步,这里以操作XMLType类型为例. 第 ...

  3. 学习Spring Boot:(十二)Mybatis 中自定义枚举转换器

    前言 在 Spring Boot 中使用 Mybatis 中遇到了字段为枚举类型,数据库存储的是枚举的值,发现它不能自动装载. 解决 内置枚举转换器 MyBatis内置了两个枚举转换器分别是:org. ...

  4. 通过mybatis自定义参数类型转换器,进行数据库字段加密脱敏

    1 问题背景 在数据库存储人员的信息时,有一些信息是敏感数据,如身份证号.出生地等.为了防止信息泄漏,这些信息不允许直接在数据库中查看,此时就需要对这些字段进行加密存储,但在页面查看的仍旧是解密后的数 ...

  5. 使用 mybatis 自定义日期类型转换器

    文章目录 前言 一.resources 1.1 sqlMapConfig.xml 1.2 log4j.properties 1.3 userMapper.xml 二.java结构 2.1 dao 2. ...

  6. springmvc中的类型转换器

    在使用springmvc时可能使用@RequestParam注解或者@RequestBody注解,他们的作用是把请求体中的参数取出来,给方法的参数绑定值. 假如方法的参数是自定义类型,就要用到类型转换 ...

  7. Struts2中自定义类型转换器

    Struts2虽然提供了强大的类型转换机制,但是有的情况还是需要程序员手动去转换. 同样拿经典的用户登录功能: <h2>局部类型转换器</h2><s:form actio ...

  8. SpringMVC中自定义类型转换器

    2019独角兽企业重金招聘Python工程师标准>>> 1.首先自己写一个类型转换器,实现org.springframework.core.convert.converter.Con ...

  9. 关于mybatis中基本类型条件判断问题

    2019独角兽企业重金招聘Python工程师标准>>> 今天继续使用mybatis搭建我的网站,在sql这块有个问题 在sql的mapper中如下方式 <select id=& ...

最新文章

  1. java web项目测试_java web项目怎么测试?
  2. 生成对抗网络GAN综述
  3. php打印pre,php 打印格式化显示利器 pre
  4. .Net 自定义应用程序配置
  5. 子数组最大值设计02
  6. HDU 5703 Desert 水题 找规律
  7. php验证百度云doc,百度云推送通知埋的大大的坑,成功测试REST API for PHP服务端...
  8. 「LibreOJ Round #11」Misaka Network 与求和(杜教筛 + Min_25)
  9. php输出12个月,php获取12个月内的开始时间和结束时间
  10. 时间序列异常检测机制的研究
  11. SQL导入Excel数据时,数字中混有字符将导致数据丢失的解决办法
  12. 【AC】九度OJ题目1153:括号匹配问题
  13. nginx的addition模块在响应的前后报文添加内容与变量的运行原理
  14. 【笔记】知行合一王阳明:1472~1529
  15. 体细胞选择区分癌基因和抑癌基因
  16. 如何快速将MKV格式转换成MP4高清电影格式?
  17. NBOOT分析-S3C244xInit.s(1)
  18. Canon MF113W激光打印机双面打印方法
  19. 计算机中软键盘有哪些用途,电脑键盘的每个字母都有什么用途呢?
  20. Vue中 v-vif 与v-for 的问题

热门文章

  1. 系统指纹 中间指纹 web指纹 识别简介
  2. dnslog 在 sql注入中的应用
  3. centos7 ntp设置 时间同步
  4. SSPI简介 windows专用GSSAPI
  5. docker 容器 defunct 僵尸进程
  6. python3 value查key的三种方法
  7. linux Rootkit:x86与ARM的内联内核函数Hooking
  8. CentOS下g++: command not found问题的解决
  9. 内核分析PE获取DLL导出函数地址
  10. VS2010不能断点/下断的问题