mybatis官网参考文档-XML配置_typeHandlers(版本: 3.4.6-SNAPSHOT)

来源:互联网 发布:淘宝店铺设置自动回复 编辑:程序博客网 时间:2024/05/18 00:39

XML 映射配置文件

typeHandlers

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

NOTE Since version 3.4.5, The MyBatis has been supported JSR-310(Date and Time API) by default.

类型处理器Java 类型JDBC 类型BooleanTypeHandlerjava.lang.Booleanboolean数据库兼容的 BOOLEANByteTypeHandlerjava.lang.Bytebyte数据库兼容的 NUMERIC 或 BYTEShortTypeHandlerjava.lang.Shortshort数据库兼容的 NUMERIC 或 SHORT INTEGERIntegerTypeHandlerjava.lang.Integerint数据库兼容的 NUMERIC 或 INTEGERLongTypeHandlerjava.lang.Longlong数据库兼容的 NUMERIC 或 LONG INTEGERFloatTypeHandlerjava.lang.Floatfloat数据库兼容的 NUMERIC 或 FLOATDoubleTypeHandlerjava.lang.Doubledouble数据库兼容的 NUMERIC 或 DOUBLEBigDecimalTypeHandlerjava.math.BigDecimal数据库兼容的 NUMERIC 或 DECIMALStringTypeHandlerjava.lang.StringCHARVARCHARClobReaderTypeHandlerjava.io.Reader-ClobTypeHandlerjava.lang.StringCLOBLONGVARCHARNStringTypeHandlerjava.lang.StringNVARCHARNCHARNClobTypeHandlerjava.lang.StringNCLOBBlobInputStreamTypeHandlerjava.io.InputStream-ByteArrayTypeHandlerbyte[]数据库兼容的字节流类型BlobTypeHandlerbyte[]BLOBLONGVARBINARYDateTypeHandlerjava.util.DateTIMESTAMPDateOnlyTypeHandlerjava.util.DateDATETimeOnlyTypeHandlerjava.util.DateTIMESqlTimestampTypeHandlerjava.sql.TimestampTIMESTAMPSqlDateTypeHandlerjava.sql.DateDATESqlTimeTypeHandlerjava.sql.TimeTIMEObjectTypeHandlerAnyOTHER 或未指定类型EnumTypeHandlerEnumeration TypeVARCHAR-任何兼容的字符串类型,存储枚举的名称(而不是索引)EnumOrdinalTypeHandlerEnumeration Type任何兼容的 NUMERIC 或 DOUBLE 类型,存储枚举的索引(而不是名称)。InstantTypeHandlerjava.time.InstantTIMESTAMPLocalDateTimeTypeHandlerjava.time.LocalDateTimeTIMESTAMPLocalDateTypeHandlerjava.time.LocalDateDATELocalTimeTypeHandlerjava.time.LocalTimeTIMEOffsetDateTimeTypeHandlerjava.time.OffsetDateTimeTIMESTAMPOffsetTimeTypeHandlerjava.time.OffsetTimeTIMEZonedDateTimeTypeHandlerjava.time.ZonedDateTimeTIMESTAMPYearTypeHandlerjava.time.YearINTEGERMonthTypeHandlerjava.time.MonthINTEGERYearMonthTypeHandlerjava.time.YearMonthVARCHAR or LONGVARCHARJapaneseDateTypeHandlerjava.time.chrono.JapaneseDateDATE

你可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。 具体做法为:实现 org.apache.ibatis.type.TypeHandler 接口, 或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler, 然后可以选择性地将它映射到一个 JDBC 类型。比如:

// ExampleTypeHandler.java@MappedJdbcTypes(JdbcType.VARCHAR)public class ExampleTypeHandler extends BaseTypeHandler<String> {  @Override  public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {    ps.setString(i, parameter);  }  @Override  public String getNullableResult(ResultSet rs, String columnName) throws SQLException {    return rs.getString(columnName);  }  @Override  public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {    return rs.getString(columnIndex);  }  @Override  public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {    return cs.getString(columnIndex);  }}
<!-- mybatis-config.xml --><typeHandlers>  <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/></typeHandlers>

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

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

  • 在类型处理器的配置元素(typeHandler element)上增加一个 javaType 属性(比如:javaType="String");
  • 在类型处理器的类上(TypeHandler class)增加一个 @MappedTypes 注解来指定与其关联的 Java 类型列表。 如果在 javaType 属性中也同时指定,则注解方式将被忽略。

可以通过两种方式来指定被关联的 JDBC 类型:

  • 在类型处理器的配置元素上增加一个 jdbcType 属性(比如:jdbcType="VARCHAR");
  • 在类型处理器的类上(TypeHandler class)增加一个 @MappedJdbcTypes 注解来指定与其关联的 JDBC 类型列表。 如果在 jdbcType 属性中也同时指定,则注解方式将被忽略。

当决定在ResultMap中使用某一TypeHandler时,此时java类型是已知的(从结果类型中获得),但是JDBC类型是未知的。 因此Mybatis使用javaType=[TheJavaType], jdbcType=null的组合来选择一个TypeHandler。 这意味着使用@MappedJdbcTypes注解可以限制TypeHandler的范围,同时除非显示的设置,否则TypeHandler在ResultMap中将是无效的。 如果希望在ResultMap中使用TypeHandler,那么设置@MappedJdbcTypes注解的includeNullJdbcType=true即可。 然而从Mybatis 3.4.0开始,如果只有一个注册的TypeHandler来处理Java类型,那么它将是ResultMap使用Java类型时的默认值(即使没有includeNullJdbcType=true)。

最后,可以让 MyBatis 为你查找类型处理器:

<!-- mybatis-config.xml --><typeHandlers>  <package name="org.mybatis.example"/></typeHandlers>

注意在使用自动检索(autodiscovery)功能的时候,只能通过注解方式来指定 JDBC 的类型。

你能创建一个泛型类型处理器,它可以处理多于一个类。为达到此目的, 需要增加一个接收该类作为参数的构造器,这样在构造一个类型处理器的时候 MyBatis 就会传入一个具体的类。

//GenericTypeHandler.javapublic class GenericTypeHandler<E extends MyObject> extends BaseTypeHandler<E> {  private Class<E> type;  public GenericTypeHandler(Class<E> type) {    if (type == null) throw new IllegalArgumentException("Type argument cannot be null");    this.type = type;  }  ...

EnumTypeHandler 和 EnumOrdinalTypeHandler 都是泛型类型处理器(generic TypeHandlers), 我们将会在接下来的部分详细探讨。

处理枚举类型

若想映射枚举类型 Enum,则需要从 EnumTypeHandler 或者 EnumOrdinalTypeHandler 中选一个来使用。

比如说我们想存储取近似值时用到的舍入模式。默认情况下,MyBatis 会利用 EnumTypeHandler 来把 Enum 值转换成对应的名字。

注意 EnumTypeHandler 在某种意义上来说是比较特别的,其他的处理器只针对某个特定的类,而它不同,它会处理任意继承了 Enum 的类。

不过,我们可能不想存储名字,相反我们的 DBA 会坚持使用整形值代码。那也一样轻而易举: 在配置文件中把 EnumOrdinalTypeHandler 加到 typeHandlers 中即可, 这样每个 RoundingMode 将通过他们的序数值来映射成对应的整形。

<!-- mybatis-config.xml --><typeHandlers>  <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="java.math.RoundingMode"/></typeHandlers>

但是怎样能将同样的 Enum 既映射成字符串又映射成整形呢?

自动映射器(auto-mapper)会自动地选用 EnumOrdinalTypeHandler 来处理, 所以如果我们想用普通的 EnumTypeHandler,就非要为那些 SQL 语句显式地设置要用到的类型处理器不可。

(下一节才开始讲映射器文件,所以如果是首次阅读该文档,你可能需要先越过这一步,过会再来看。)

<!DOCTYPE mapper    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"    "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="org.apache.ibatis.submitted.rounding.Mapper"><resultMap type="org.apache.ibatis.submitted.rounding.User" id="usermap"><id column="id" property="id"/><result column="name" property="name"/><result column="funkyNumber" property="funkyNumber"/><result column="roundingMode" property="roundingMode"/></resultMap><select id="getUser" resultMap="usermap">select * from users</select><insert id="insert">    insert into users (id, name, funkyNumber, roundingMode) values (    #{id}, #{name}, #{funkyNumber}, #{roundingMode}    )</insert><resultMap type="org.apache.ibatis.submitted.rounding.User" id="usermap2"><id column="id" property="id"/><result column="name" property="name"/><result column="funkyNumber" property="funkyNumber"/><result column="roundingMode" property="roundingMode" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/></resultMap><select id="getUser2" resultMap="usermap2">select * from users2</select><insert id="insert2">    insert into users2 (id, name, funkyNumber, roundingMode) values (    #{id}, #{name}, #{funkyNumber}, #{roundingMode, typeHandler=org.apache.ibatis.type.EnumTypeHandler}    )</insert></mapper>

注意,这里的 select 语句强制使用 resultMap 来代替 resultType


阅读全文
0 0