Mybatis配置-类型处理器(typeHandlers)

发布时间:2023年12月18日

每当MyBatis设置PreparedStatement的参数或从ResultSet中检索值时,都会使用TypeHandler以适合Java类型的方式来检索值。下表描述了默认的TypeHandlers。

自MyBatis 3.4.5版本起,默认支持JSR-310(日期和时间API)。

Type HandlerJava TypesJDBC Types
BooleanTypeHandlerjava.lang.Boolean,?booleanAny compatible?BOOLEAN
ByteTypeHandlerjava.lang.Byte,?byteAny compatible?NUMERIC?or?BYTE
ShortTypeHandlerjava.lang.Short,?shortAny compatible?NUMERIC?or?SMALLINT
IntegerTypeHandlerjava.lang.Integer,?intAny compatible?NUMERIC?or?INTEGER
LongTypeHandlerjava.lang.Long,?longAny compatible?NUMERIC?or?BIGINT
FloatTypeHandlerjava.lang.Float,?floatAny compatible?NUMERIC?or?FLOAT
DoubleTypeHandlerjava.lang.Double,?doubleAny compatible?NUMERIC?or?DOUBLE
BigDecimalTypeHandlerjava.math.BigDecimalAny compatible?NUMERIC?or?DECIMAL
StringTypeHandlerjava.lang.StringCHAR,?VARCHAR
ClobReaderTypeHandlerjava.io.Reader-
ClobTypeHandlerjava.lang.StringCLOB,?LONGVARCHAR
NStringTypeHandlerjava.lang.StringNVARCHAR,?NCHAR
NClobTypeHandlerjava.lang.StringNCLOB
BlobInputStreamTypeHandlerjava.io.InputStream-
ByteArrayTypeHandlerbyte[]Any compatible byte stream type
BlobTypeHandlerbyte[]BLOB,?LONGVARBINARY
DateTypeHandlerjava.util.DateTIMESTAMP
DateOnlyTypeHandlerjava.util.DateDATE
TimeOnlyTypeHandlerjava.util.DateTIME
SqlTimestampTypeHandlerjava.sql.TimestampTIMESTAMP
SqlDateTypeHandlerjava.sql.DateDATE
SqlTimeTypeHandlerjava.sql.TimeTIME
ObjectTypeHandlerAnyOTHER, or unspecified
EnumTypeHandlerEnumeration TypeVARCHAR?any string compatible type, as the code is stored (not index).
EnumOrdinalTypeHandlerEnumeration TypeAny compatible?NUMERIC?or?DOUBLE, as the position is stored (not the code itself).
SqlxmlTypeHandlerjava.lang.StringSQLXML
InstantTypeHandlerjava.time.InstantTIMESTAMP
LocalDateTimeTypeHandlerjava.time.LocalDateTimeTIMESTAMP
LocalDateTypeHandlerjava.time.LocalDateDATE
LocalTimeTypeHandlerjava.time.LocalTimeTIME
OffsetDateTimeTypeHandlerjava.time.OffsetDateTimeTIMESTAMP
OffsetTimeTypeHandlerjava.time.OffsetTimeTIME
ZonedDateTimeTypeHandlerjava.time.ZonedDateTimeTIMESTAMP
YearTypeHandlerjava.time.YearINTEGER
MonthTypeHandlerjava.time.MonthINTEGER
YearMonthTypeHandlerjava.time.YearMonthVARCHAR?or?LONGVARCHAR
JapaneseDateTypeHandlerjava.time.chrono.JapaneseDateDATE

?您可以覆盖或创建自己的TypeHandler来处理不受支持或非标准的类型。为此,您需要实现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>

使用这样的TypeHandler会覆盖Java String属性和VARCHAR参数和结果的现有TypeHandler。请注意,MyBatis不会根据数据库元数据进行内省来确定类型,因此必须在参数和结果映射中指定它是一个VARCHAR字段,以便连接正确的TypeHandler。这是因为直到执行语句时,MyBatis才能意识到数据类型。

MyBatis会通过TypeHandler的泛型类型来确定您想要处理的Java类型,但是您可以通过以下两种方式来覆盖这种行为:

  1. 给typeHandler元素添加javaType属性,例如:javaType="String"。这将明确指定TypeHandler所要关联的Java类型。

  2. 在TypeHandler类上添加@MappedTypes注解,指定要关联的Java类型列表。如果同时指定了javaType属性,@MappedTypes注解将被忽略。

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

  1. 给typeHandler元素添加jdbcType属性,例如:jdbcType="VARCHAR"。这将明确指定与TypeHandler关联的JDBC类型。

  2. 在TypeHandler类上添加@MappedJdbcTypes注解,指定要关联的JDBC类型列表。如果同时指定了jdbcType属性,@MappedJdbcTypes注解将被忽略。

?在决定在ResultMap中使用哪个TypeHandler时,已知Java类型(来自结果类型),但未知JDBC类型。因此,MyBatis将使用组合javaType=[Java类型],jdbcType=null来选择一个TypeHandler。这意味着使用@MappedJdbcTypes注解会限制TypeHandler的范围,并且除非明确设置,否则它将无法在ResultMap中使用。为了使一个TypeHandler可以在ResultMap中使用,可以在@MappedJdbcTypes注解上设置includeNullJdbcType=true。然而,自从Mybatis 3.4.0版本开始,如果一个单独的TypeHandler被注册用于处理一个Java类型,默认情况下它将被用于使用该Java类型的ResultMaps(即使没有includeNullJdbcType=true)。

最后,您可以让MyBatis为您的TypeHandler进行搜索:

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

?请注意,当使用自动发现功能时,只能使用注解来指定JDBC类型。

您可以创建一个通用的TypeHandler,它能够处理多个类。为此,您可以添加一个构造函数,接收一个Class作为参数,MyBatis在构造TypeHandler时将传递实际的类。

//GenericTypeHandler.java
public 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是通用的TypeHandler。

文章来源:https://blog.csdn.net/hay23455/article/details/135058232
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。