专栏首页洁癖是一只狗面试Mybatis之类型处理器​(typeHandlers)

面试Mybatis之类型处理器​(typeHandlers)

Mybatis之类型处理器

无论是MyBatis在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型,下表描述了一些默认的类型处理器.

类型处理器

Java 类型

JDBC 类型

BooleanTypeHandler

java.lang.Boolean, boolean

数据库兼容的 BOOLEAN

ByteTypeHandler

java.lang.Byte, byte

数据库兼容的 NUMERIC 或 BYTE

ShortTypeHandler

java.lang.Short, short

数据库兼容的 NUMERIC 或 SMALLINT

IntegerTypeHandler

java.lang.Integer, int

数据库兼容的 NUMERIC 或 INTEGER

LongTypeHandler

java.lang.Long, long

数据库兼容的 NUMERIC 或 BIGINT

FloatTypeHandler

java.lang.Float, float

数据库兼容的 NUMERIC 或 FLOAT

DoubleTypeHandler

java.lang.Double, double

数据库兼容的 NUMERIC 或 DOUBLE

BigDecimalTypeHandler

java.math.BigDecimal

数据库兼容的 NUMERIC 或 DECIMAL

StringTypeHandler

java.lang.String

CHAR, VARCHAR

ClobReaderTypeHandler

java.io.Reader

-

ClobTypeHandler

java.lang.String

CLOB, LONGVARCHAR

NStringTypeHandler

java.lang.String

NVARCHAR, NCHAR

NClobTypeHandler

java.lang.String

NCLOB

BlobInputStreamTypeHandler

java.io.InputStream

-

ByteArrayTypeHandler

byte[]

数据库兼容的字节流类型

BlobTypeHandler

byte[]

BLOB, LONGVARBINARY

DateTypeHandler

java.util.Date

TIMESTAMP

DateOnlyTypeHandler

java.util.Date

DATE

TimeOnlyTypeHandler

java.util.Date

TIME

SqlTimestampTypeHandler

java.sql.Timestamp

TIMESTAMP

SqlDateTypeHandler

java.sql.Date

DATE

SqlTimeTypeHandler

java.sql.Time

TIME

ObjectTypeHandler

Any

OTHER 或未指定类型

EnumTypeHandler

Enumeration Type

VARCHAR 或任何兼容的字符串类型,用以存储枚举的名称(而不是索引值)

EnumOrdinalTypeHandler

Enumeration Type

任何兼容的 NUMERIC 或 DOUBLE 类型,存储枚举的序数值(而不是名称)。

SqlxmlTypeHandler

java.lang.String

SQLXML

InstantTypeHandler

java.time.Instant

TIMESTAMP

LocalDateTimeTypeHandler

java.time.LocalDateTime

TIMESTAMP

LocalDateTypeHandler

java.time.LocalDate

DATE

LocalTimeTypeHandler

java.time.LocalTime

TIME

OffsetDateTimeTypeHandler

java.time.OffsetDateTime

TIMESTAMP

OffsetTimeTypeHandler

java.time.OffsetTime

TIME

ZonedDateTimeTypeHandler

java.time.ZonedDateTime

TIMESTAMP

YearTypeHandler

java.time.Year

INTEGER

MonthTypeHandler

java.time.Month

INTEGER

YearMonthTypeHandler

java.time.YearMonth

VARCHAR 或 LONGVARCHAR

JapaneseDateTypeHandler

java.time.chrono.JapaneseDate

DATE

你可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型,具体做法为:实现 org.apache.ibatis.type.TypeHandler 接口,或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler我们就举一个简单的例子,我们先看个实体类.

public class Student {

    private int id;

    private String name;

    private boolean pass;//注意他的类型是布尔。我们要把他转成int放到数据库
    //get 和 set 省略
}

第一步:实现TypeHandler

package com.jiepi.util;

import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;

import java.sql.*;


public class MyTypeHandler implements TypeHandler {
    //在设置参数的时候调用
    public void setParameter(PreparedStatement preparedStatement, int i, Object param, JdbcType jdbcType) throws SQLException {
        if (param == null) {
            preparedStatement.setInt(i,0);
            return;
        }
        Boolean pass = (Boolean) param;
        int value = pass ? 1 : 0;
        preparedStatement.setInt(i,value);
    }
    //从数据库获取数据调用
    public Object getResult(ResultSet resultSet, String s) throws SQLException {
        int value = resultSet.getInt(s);
        if (value == 1) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }
    public Object getResult(ResultSet resultSet, int i) throws SQLException {
        int value = resultSet.getInt(i);
        if (value == 1) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }
    public Object getResult(CallableStatement callableStatement, int i) throws SQLException {
        int value = callableStatement.getInt(i);
        if (value == 1) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }
}

第二步:在mybatis配置注册TypeHandler(myBatis-config.xml).

<typeHandlers>
    <typeHandler handler="com.jiepi.util.MyTypeHandler" jdbcType="NUMERIC" javaType="java.lang.Boolean"/>
</typeHandlers>

第三步:在映射文件中设置使用TypeHandler.

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

 <resultMap id="studentMap" type="com.jiepi.beans.Student">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="pass" column="pass" typeHandler="com.jiepi.util.MyTypeHandler" jdbcType="NUMERIC" javaType="java.lang.Boolean"/>
    </resultMap>

    <insert id="add">//typeHandler 是没有双引号的
        INSERT INTO Student (id, name, pass) VALUES (#{id}, #{name}, #{pass,jdbcType=NUMERIC,javaType=java.lang.Boolean,typeHandler=com.jiepi.util.MyTypeHandler})
    </insert>

    <select id="find" resultMap="studentMap">
        SELECT * FROM Student
    </select>

第四步:测试结果.

     @Test
    public void find() {
        StudentMapper dao = session.getMapper(StudentMapper.class);
        List<Student> student = dao.find();
        student.stream().map(it->it.toString()).forEach(System.out::println);
        System.out.println(student);
    }
    @Test
    public void add1() {
        StudentMapper dao = session.getMapper(StudentMapper.class);
        Student student = new Student();
        student.setName("jiepi");
        student.setPass(true);//这里是boolean
        dao.add(student);
        session.commit();
    }

运行结果:

[DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@15a34df2]
[DEBUG] ==>  Preparing: INSERT INTO Student (id, name, pass) VALUES (?, ?, ?) 
int int 
[DEBUG] ==> Parameters: 0(Integer), jiepi(String), 1(Integer)//这里变成了1
[DEBUG] <==    Updates: 1
[DEBUG] Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@15a34df2]
Disconnected from the target VM, address: '127.0.0.1:51494', transport: 'socket'

1.当然也还可以使用注解分别是MappedJdbcTypes和MappedTypes代替映射文件里面的jdbcType 和javeType.

2.mybatis配置文件上面的配置只能一个个的去配置类型处理,因此我们还可以自动查找查找类型处理器.

  <typeHandlers>
       <package name="com.jiepi.util"/>
  </typeHandlers>

本文分享自微信公众号 - 洁癖是一只狗(rookie-dog),作者:洁癖

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-08-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Mysql如何给字符串添加索引(前缀索引)

    在日常开发中,我们经常给字符串添加索引,那么给字段添加索引有什么技巧吗,我们看看下面的例子,我们给一个邮箱添加索引,应该如何添加呢

    小土豆Yuki
  • Mysql索引解密(上)

    索引是数据库概念最重要的概念之一,也是我们经常要使用的优化手段,索引的出现其实就是为了提高数据查询的效率,就像书的目录一样

    小土豆Yuki
  • Mysql索引解密(下)

    上面ID索引树进行查找记录的过程叫回表,可以看出k树索引树进行了三次查询,Id索引树进行了两次查询。查询数据过程中是否可以避免回表查询呢,

    小土豆Yuki
  • python国际化(i18n)和中英文切

    Python通过gettext模块支持国际化(i18n),可以实现程序的多语言界面的支持,下面是我的多语言支持实现:

    py3study
  • 如何配置关联Python 解释器 Anaconda的教程(图解)

    我们点击Project 这一栏下的 Project Interpreter 之后我们点击红色小方框 的小箭头

    砸漏
  • MeanShift算法C++解析(三)

    最后是最重要的核心啦,就是MeanShift_Tracking这个函数。同样的,我们先来看看这个函数的内部变量。

    钱塘小甲子
  • LeetCode 40. Combination Sum II

    ShenduCC
  • LeetCode 39. Combination Sum

    ShenduCC
  • 【C语言笔记】变参函数

    提到变参函数,我们的感觉是不是既熟悉又陌生?感觉熟悉是因为我们平时都在使用着,如我们常使用的printf()函数与scanf()函数就是典型的变参函数。因为pr...

    正念君
  • 默认模式网络下的自动化信息处理

    爱因斯坦邀请您关注思影科技! 近日,来自剑桥大学的Deniz等人在PNAS上发文,主要讲述了DMN网络对个体自动信息处理的控制。个体在一系列复杂的心理过程中,会...

    用户1279583

扫码关注云+社区

领取腾讯云代金券