MyBatis类型处理器TypeHandler的作用及说明
目录
- 为什么需要 TypeHandler?
- TypeHandler 的作用
- TypeHandler 的接口定义
- MyBATis 内置的 TypeHandler
- 自定义 TypeHandler
- 自定义 TypeHandler 的步骤
- 总结
TypeHandler
是 MyBatis 中用于处理 Java 类型与 JDBC 类型之间转换的接口。它在 MyBatis 的参数绑定和结果映射过程中起着至关重要的作用。
为什么需要 TypeHandler?
Java 和 数据库(JDBC)使用不同的类型系统。例如:
- Java 中有
String
、Integer
、Date
、Boolean
、enum
等类型。 - JDBC 中有
VARCHAR
、INTEGER
、DATE
、BOOLEAN
、TIMESTAMP
、BLOB
等类型。
当 MyBatis 执行 SQL 语句时,需要将 Java 对象中的数据设置到 JDBC 的 PreparedStatement
中(参数绑定),以及将 JDBC 的 ResultSet
中的数据转换为 Java 对象(结果映射)。TypeHandler
就负责处理这两种情况下的类型转换。
TypeHandler 的作用
参数绑定 (Java 类型 -> JDBC 类型):
- 当 MyBatis 将 Java 对象中的数据设置到
PreparedStatement
的占位符(#{}
)时,TypeHandler
会将 Java 类型转换为对应的 JDBC 类型。 - 例如,将 Java 的
String
类型转换为 JDBC 的VARCHAR
类型,将 Java 的Date
类型转换为 JDBC 的TIMESTAMP
类型。
结果映射 (JDBC 类型 -> Java 类型):
- 当 MyBatis 从
ResultSet
中读取数据并将其映射为 Java 对象时,TypeHandler
会将 JDBC 类型转换为对应的 Java 类型。 - 例如,将 JDBC 的
VARCHAR
类型转换为 Java 的String
类型,将 JDBC 的INTEGER
类型转换为 Java 的Integer
类型。
TypeHandler 的接口定义
public interface TypeHandler<T> { // 参数绑定:将 Java 类型转换为 JDBC 类型,并设置到 PreparedStatement 中 void setParameter(PreparedStatement ps, int i, T parameter, J编程客栈dbcType jdbcType) throws SQLException; // 结果映射:从 ResultSet 中获取指定列的数据,并将其转换为 Java 类型 T getResult(ResultSet rs, String columnName) throws SQLException; // 结果映射:从 ResultSet 中获取指定列索引的数据,并将其转换为 Java 类型 T getResult(ResultSet rs, int columnIndex) throws SQLException; // 结果映射:从 CallableStatement 中获取指定列索引的数据,将其转换为java类型 T getResult(CallableStatement cs, int columnIndex) throws SQLException; }
setParameter()
: 将 Java http://www.devze.com类型的参数parameter
设置到PreparedStatement
的第i
个占位符,并指定 JDBC 类型jdbcType
(jdbcType
可以为空,MyBatis 会尝试自动推断)。getResult()
: 有三个重载方法,分别根据列名、列索引从ResultSet
中获取数据,或从CallableStatement
获取数据,并将其转换为 Java 类型。
MyBatis 内置的 TypeHandler
MyBatis 内置了许多常用的 TypeHandler
,用于处理常见的类型转换。例如:
StringTypeHandler
: 处理String
类型。IntegerTypeHandler
: 处理Integer
类型。LongTypeHandler
: 处理Long
类型。DateTypeHandler
: 处理java.util.Date
类型。BooleanTypeHandler
: 处理Boolean
类型。EnumTypeHandler
: 处理枚举类型(默认使用枚举的名称)。EnumOrdinalTypeHandler
: 处理枚举类型(使用枚举的序数)。BlobTypeHandler
: 处理二进制大对象 (BLOB)。ClobTypeHandler
: 处理字符大对象 (CLOB)。SqlDateTypeHandler
:处理java.sql.Date
类型SqlTimeTypeHandler
:处理java.sql.Time
类型SqlTimestampTypeHandler
:处理java.sql.Timestamp
类型- …
自定义 TypeHandler
当 MyBatis 内置的 TypeHandler
不能满足需求时,我们可以自定义 TypeHandler
。例如:
- 处理特殊类型: 例如,将数据库中的 jsON 字符串转换为 Java 对象,或者将 Java 对象转换为 JSON 字符串存储到数据库中。
- 自定义类型转换逻辑: 例如,对日期类型进行特殊的格式化,或者对枚举类型使用自定义的转换规则。
自定义 TypeHandler 的步骤
1.实现 TypeHandler
接口: 创建一个类,实现 TypeHandler
接口,并实现接口中的方法。
2.注册 TypeHandler: 有两种方式注册自定义的 TypeHandler
:
- XML 配置: 在
mybatis-config.xml
文件中,使用<typeHandlers>
标签注册TypeHandler
。
<typeHandlers> <typeHandler handler="com.example.MyTypeHandler" javaType="com.example.MyType" jdbcType="VARCHAR"/> </typeHandlers>
- 或者使用包扫描:
<typeHandlers> <package name="com.example.typehandler"/> </typeHandlers>
- 注解配置: 在自定义的
TypeHandler
类上使用@MappedTypes
和@MappedJdbcTypes
注解。
@MappedTypes(MyType.class) // 指定 Java 类型 @MappedJdbcTypes(JdbcType.VARCHAR) // 指定 JDBC 类型 public class MyTypeHandler implements TypeHandler<MyType> { // ... 实现 TypeHandler 接口的方法 ... }
3.指定jdbcType(可选): 如果MyBatis无法推断,则必须通过jdbcType
属性为null
值指定数据库列的类型
- 示例:
- 自定义一个将数据库中的 VARCHAR 类型转换为 Java 中的枚举类型的 TypeHandler:
// 假设有一个枚举类型 public enum Status { ACTIVE, INACTIVE, PENDING } // 自定义 TypeHandler @MappedTypes(Status.class) @MappedJdbcTypes(JdbcType.VARCHAR) public class StatusTypeHandler implements TypeHandler<Status> { @Overjavascriptride public void setParameter(PreparedStatement ps, int i, Status parameter, JdbcType jdbcType) throws SQLException { if (parameter == null) { ps.setString(i, null); } else { ps.setString(i, parameter.name()); // 将枚举的名称存储到数据库 } } @Override public Status getResult(ResultSet rs, String columnName) throws SQLException { String value = rs.getString(columnName); return getStatus(value); } @Override public Status getResult(ResultSet rs, int columnIndex) throws SQLException { String value = rs.getString(columnIndex); return getStatus(value); } @Override public Status getResult(CallableStatement cs, int columnIndex) throws SQLException { String value = cs.getString(columnIndex); return getStatus(value); } private Status getStatus(String value){ if (value == null) { return null; } try { return Status.valueOf(value); // 根据名称从数据库中获取枚举值 } catch (IllegalArgumentException e) { return null; // 或者抛出异常 } } } // 在 mybatis-config.xml 中注册 TypeHandler <typeHandlers> <typeHandler handler="com.example.StatusTypeHandler"/> </typeHandlers> // 或者在 Mapper XML 文件中使用 <resultMap id="userResultMap" type="User"> <result property="status" column="status" javaType="com.example.Status" jdbcType="VARCHAR" typeHa编程客栈ndler="com.example.StatusTypeHandler"/> </resultMap>
总结
TypeHandler
是 MyBatis 中用于处理 Java 类型与 JDBC 类型之间转换的关键组件。
MyBatis 内置了许多常用的 TypeHandler
,在大多数情况下,我们可以直接使用内置的 TypeHCSbvzgandler
。
当需要处理特殊类型或自定义类型转换逻辑时,我们可以自定义 TypeHandler
,并通过 XML 配置或注解的方式注册自定义的 TypeHandler
。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。
精彩评论