TypeHandler
是 MyBatis 中用于处理 Java 类型和 JDBC 类型之间转换的组件。通过自定义 TypeHandler
,可以实现复杂的类型映射逻辑,例如将 Java 中的 long
类型与数据库中的 VARCHAR
类型进行转换。以下是 TypeHandler
的详细使用方法:
1. TypeHandler
的作用
- 类型转换:将 Java 类型与 JDBC 类型进行双向转换。
- 自定义逻辑 :实现复杂的类型映射逻辑,例如将
long
转换为String
,或将 JSON 字符串映射为 Java 对象。 - 增强灵活性:解决 MyBatis 默认类型处理器无法处理的特殊场景。
2. 自定义 TypeHandler
的实现步骤
步骤 1:创建自定义 TypeHandler
自定义 TypeHandler
需要继承 BaseTypeHandler
或实现 TypeHandler
接口,并重写以下方法:
setNonNullParameter
:将 Java 类型转换为 JDBC 类型。getNullableResult
:将 JDBC 类型转换为 Java 类型(有多个重载方法)。
示例:实现 Long
与 String
的转换
java
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class LongToStringTypeHandler extends BaseTypeHandler<Long> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Long parameter, JdbcType jdbcType) throws SQLException {
// 将 Long 类型转换为 String 类型,并设置到 PreparedStatement 中
ps.setString(i, parameter.toString());
}
@Override
public Long getNullableResult(ResultSet rs, String columnName) throws SQLException {
// 从 ResultSet 中获取 String 类型的值,并转换为 Long 类型
String value = rs.getString(columnName);
return value == null ? null : Long.parseLong(value);
}
@Override
public Long getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
// 从 ResultSet 中获取 String 类型的值,并转换为 Long 类型
String value = rs.getString(columnIndex);
return value == null ? null : Long.parseLong(value);
}
@Override
public Long getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
// 从 CallableStatement 中获取 String 类型的值,并转换为 Long 类型
String value = cs.getString(columnIndex);
return value == null ? null : Long.parseLong(value);
}
}
步骤 2:在实体类中指定 TypeHandler
在实体类的字段上使用 @TableField
注解(MyBatis-Plus)或 @TypeHandler
注解(MyBatis),指定自定义的 TypeHandler
。
示例:在 MyBatis-Plus 中使用
java
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import org.apache.ibatis.type.JdbcType;
@TableName("your_table")
public class YourEntity {
@TableField(value = "your_column", jdbcType = JdbcType.VARCHAR, typeHandler = LongToStringTypeHandler.class)
private Long yourColumn; // 使用 long 类型
// Getter 和 Setter 方法
}
步骤 3:在 MyBatis 配置中注册 TypeHandler
如果使用的是 MyBatis(非 MyBatis-Plus),需要在 MyBatis 配置文件中注册自定义 TypeHandler
。
示例:在 mybatis-config.xml
中注册
xml
<typeHandlers>
<typeHandler handler="com.example.LongToStringTypeHandler"/>
</typeHandlers>
检查下项目配置application.properties
是否包含自己定义的转换器路径
yaml
mybatis-plus.type-handlers-package=自己的包路径
如下: mybatis-plus.type-handlers-package=com.xxx.type.handler
3. TypeHandler
的使用场景
场景 1:基本类型与字符串的转换
- 例如:将
long
类型与VARCHAR
类型相互转换。
场景 2:复杂对象的序列化与反序列化
- 例如:将 Java 对象序列化为 JSON 字符串存储到数据库,或从数据库读取 JSON 字符串并反序列化为 Java 对象。
示例:JSON 与 Java 对象的转换
java
复制
java
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JsonTypeHandler<T> extends BaseTypeHandler<T> {
private static final ObjectMapper objectMapper = new ObjectMapper();
private final Class<T> type;
public JsonTypeHandler(Class<T> type) {
this.type = type;
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
ps.setString(i, objectMapper.writeValueAsString(parameter));
}
@Override
public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
String value = rs.getString(columnName);
return value == null ? null : objectMapper.readValue(value, type);
}
@Override
public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String value = rs.getString(columnIndex);
return value == null ? null : objectMapper.readValue(value, type);
}
@Override
public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String value = cs.getString(columnIndex);
return value == null ? null : objectMapper.readValue(value, type);
}
}
4. 注意事项
- 类型匹配 :确保
TypeHandler
处理的 Java 类型与数据库字段类型匹配。 - 性能影响:复杂的类型转换可能会影响性能,尽量避免在频繁查询的场景中使用。
- 线程安全 :确保
TypeHandler
的实现是线程安全的。
5. 总结
-
TypeHandler
是 MyBatis 中用于处理类型转换的核心组件 ,通过自定义TypeHandler
可以实现复杂的类型映射逻辑。 -
使用步骤:
- 创建自定义
TypeHandler
。 - 在实体类中指定
TypeHandler
。 - 在 MyBatis 配置中注册
TypeHandler
(如果需要)。
- 创建自定义
-
适用场景:基本类型与字符串的转换、复杂对象的序列化与反序列化等。
通过合理使用 TypeHandler
,可以解决 MyBatis 中类型不匹配的问题,并增强代码的灵活性和可维护性。
参考:
可参考mybatis-plus 中的例子 com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler