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

我们执行sql语句通过PreparedStatement语句实现,PreparedStatement会设置?值,类型处理器帮PreparedStatement找到对应的set方法,到底是选择setIntsetStringsetDate...

注意:类型处理器默认可以处理基本的数据类型以及对应的包装类,uitl.Date、sql.Date等,但无法默认处理自定义类型。

MyBatis将一个Java对象作为输入参数执行INSERT语句操作时,它会创建一个PreparedStatement对象,并且使用setXXX()方法对占位符设置相应的参数值。这里,XXX可以是IntStringDateJava对象属性类型的任意一个。示例如下:

<insert id="insertStudent" parameterType="Student"> INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,DOB)  VALUES(#{studId},#{name},#{email},#{dob})
</insert>

为了执行这个语句,MyBatis将采取以下一系列动作:

创建一个有占位符的PreparedStatement接口,如下:

PreparedStatement ps = connection.prepareStatement("INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,DOB) VALUES(?,?,?,?)");

检查Student对象的属性studId的类型,然后使用合适setXXX()方法去设置参数值。这里studIdInteger类型,所以会使用setInt()方法:

ps.setInt(1,student.getStudId());

类似地,对于nameemail属性都是String类型的,MyBatis使用setString()方法设置参数。

至于dob属性, MyBatis会使用setDate()方法设置dob处占位符位置的值。MyBaits会将java.util.Date类型转换为java.sql.Timestamp并设值:

ps.setTimestamp(4, new Timestamp((student.getDob()).getTime()));

MyBatis是怎么知道对于Integer类型属性使用setInt()String类型属性使用setString()方法呢?其实MyBatis是通过使用类型处理器typeHandlers来决定这么做的。

MyBatis对于以下的类型使用内建的类型处理器:所有的基本数据类型、基本类型的包装类型、byte[]java.util.Datejava.sql.Datejava,sql.Timejava.sql.Timestampjava枚举类型等。所以当MyBatis发现属性的类型属于上述类型,他会使用对应的类型处理器将值设置到PreparedStatement中,同样地,当SQL结果集封装成java类对象的时候,也有类似的过程。

那如果有一个自定义的类型,怎么存储存储到数据库呢?示例如下:假设表STUDENTS 有一个 PHONE 字段,类型为 VARCHAR2(15),而 Student类有一个自定义类型PhoneNumber,这个类型包括三个属性:国家编号、区号、电话号码。

public class PhoneNumber{ private String countryCode; private String stateCode; private String number; public PhoneNumber(){ } public PhoneNumber(String countryCode, String stateCode, String number) { this.countryCode = countryCode; this.stateCode = stateCode; this.number = number; } public String getAsString() { return countryCode + "-" + stateCode + "-" + number; } // Setters and getters
} public class Student{ private Integer id; private String name; private String email; private PhoneNumber phone; // Setters and getters
}

StudentMapper.xml配置如下:

<insert id="insertStudent" parameter Type="Student"> insert into students(name,email,phone) values(#{name},#{email},#{phone})
</insert>

这个xml文件里面,参数对象中的属性phone的值需要传递给#{phone},而参数对象的属性phonePhoneNumber类型。但是,MyBatis 并不知道该怎样来处理这个类型的对象。为了让MyBatis明白怎样处理这个自定义的Java对象类型,如PhoneNumber,我们可以创建一个自定义的类型处理器,MyBatis提供了抽象类BaseTypeHandler<T> ,我们可以继承此类创建自定义类型处理器。代码如下:

package com.au.typehandlers;import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;import com.briup.pojo.PhoneNumber;public class PhoneTypeHandler extends BaseTypeHandler<PhoneNumber>{//遇到PhoneNumber参数的时候应该如何在ps中设置值@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, PhoneNumber parameter, JdbcType jdbcType)throws SQLException {ps.setString(i, parameter.getAsString());}//查询中遇到PhoneNumber类型的应该如何封装(使用列名封装)@Overridepublic PhoneNumber getNullableResult(ResultSet rs, String columnName) throws SQLException {return new PhoneNumber(rs.getString(columnName));}//查询中遇到PhoneNumber类型的应该如何封装(使用列的下标)@Overridepublic PhoneNumber getNullableResult(ResultSet rs, int columnIndex) throws SQLException {return new PhoneNumber(rs.getString(columnIndex));}//CallableStatement使用中遇到了PhoneNumber类型的应该如何封装@Overridepublic PhoneNumber getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {return new PhoneNumber(cs.getString(columnIndex));}}

注意:使用ps.setString()rs.getString()方法是因为在数据库的表中phone列是VARCHAR类型。

最后需要在mybatis-config.xml中注册这个类型处理器:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration> <properties resource="application.properties" /> <typeHandlers> <typeHandler handler="com.au.typehandlers.PhoneTypeHandler" /> </typeHandlers>
</configuration>

注册PhoneTypeHandler后,MyBatis就能够将Phone类型的对象值存储到VARCHAR类型的列上。

MyBatis自定义类型处理器(typeHandler)相关推荐

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

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

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

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

  3. Mybatis——类型处理器TypeHandler

    在日常开发中使用mybatis时,mybatis的mapper.xml.mapper接口.entity实体一般会由mybatis-generator自动生成,其中实体的每个属性与数据库表的列一一对应, ...

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

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

  5. MyBatis(九):MyBatis类型处理器(TypeHandler)详解

    TypeHandler简介 TypeHandler,顾名思义类型转换器,就是将数据库中的类型与Java中的类型进行相互转换的处理器. MyBatis 在设置预处理语句(PreparedStatemen ...

  6. 在mybatis里如何自定义类型处理器

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

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

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

  8. MyBatis之类型处理器typeHandlers

    typeHandlers类型处理器 实现java类型与数据库类型之间的转换,可以使用系统提供的类型处理器,也可以自定义类型处理器,这里介绍的是实现自定义类型处理器处理数据库类型与java类型的转换 比 ...

  9. 类型处理器TypeHandler

    作用:用于JavaType和JdbcType之间的转换 解析:当Mybatis将一个Java对象写入数据库时,它会创建一个PreparedStatument对象,并且使用setValue()方法对占位 ...

最新文章

  1. LeetCode-Unique Binary Search Trees
  2. 20321关系数据库理论基础
  3. 求字符串里面数字之和
  4. openshift命令_使用命令行工具创建WildFly OpenShift应用程序
  5. JDK Bug系统浪费时间
  6. 2018 总结 2019 展望
  7. android Instrumentation 转载
  8. 精通Android自定义View(八)绘制篇Canvas分析之绘制文本
  9. 青、取之于蓝,而青于蓝。
  10. 『007』MySQL
  11. 高通QFIL烧录错误解决方法
  12. 163邮箱链接服务器失败是怎么回事,outlook邮箱添加163邮箱账户失败该怎么办?...
  13. 地砖中间高四边低_客厅棚顶有黑镜在风水里讲怎么样 装修中橱柜里的白色色块用哪个做,怎么施工...
  14. C语言水电管理系统,小区水电费管理系统C语言.doc
  15. 中国跨境平台出海,产业带依然是最大优势
  16. java 实现仿word2007字数统计功能
  17. Redis 主从复制、哨兵和集群区别
  18. 计划订单投放成生产任务单时修改生产任务单编号
  19. python可以p图_用Python来P图!简直耍开PS几条街!
  20. Keras Regressor回归(一)

热门文章

  1. 计算机网络计算1g等于多少MB,1g等于多少mb 电脑手机内存精确数据【图文】
  2. 树状数组(Binary Index Tree)
  3. 用python给MP3加封面图片,修改作者,专辑等信息
  4. vue-cli/vue-ui
  5. 中国光大银行科技部门面试。
  6. 自动驾驶仿真——腾讯(00700)发布自动驾驶仿真平台TAD Sim 2.0,加速自动驾驶产业布局
  7. 【多线程】ThreadPool线程池
  8. 7-2 统计字符 (15 分)
  9. Vue选项之extends扩展
  10. js生成guid32位