1.1 什么是MyBatis类型处理器
想象一下你在两个语言不通的朋友之间充当翻译。MyBatis类型处理器扮演的就是这个角色——它在Java对象和数据库之间架起一座桥梁。当你的Java代码中的Date对象需要存入数据库的timestamp字段,或者从数据库读取的字符串需要转换成枚举类型时,类型处理器就在默默工作。
我刚开始接触MyBatis时,总觉得数据能自动在Java和数据库之间转换很神奇。后来才明白,这背后就是类型处理器的功劳。它负责将Java类型与JDBC类型进行相互转换,让开发人员不用手动处理这些繁琐的转换逻辑。
每个类型处理器都实现了TypeHandler接口,MyBatis已经为大多数常见类型提供了默认实现。比如字符串、数字、日期这些基础类型,你甚至感受不到它们的存在。
1.2 为什么需要自定义类型处理器
虽然MyBatis提供了丰富的内置类型处理器,但真实项目总会遇到特殊情况。上周我帮一个朋友解决了个问题:他们需要在数据库存储JSON字符串,但在Java中要自动转换成对象。内置的类型处理器显然无法满足这种需求。
另一个常见场景是枚举处理。默认情况下,MyBatis使用枚举的name()方法存储,但有时候你希望存储的是枚举的某个属性值,或者需要更复杂的映射逻辑。这时候自定义类型处理器就派上用场了。
数据库中的特殊格式也需要考虑。比如某些数据库使用特定格式存储IP地址,或者需要处理自定义的货币格式。通过自定义类型处理器,你可以封装这些转换逻辑,让业务代码保持干净。
1.3 类型处理器的基本工作原理
类型处理器的核心其实很简单。它主要包含四个方法:setParameter和getResult是其中最重要的两个。当MyBatis执行SQL语句时,setParameter方法负责将Java类型转换成JDBC类型;当从结果集读取数据时,getResult方法负责将JDBC类型转换回Java类型。
让我用一个简单例子说明。假设你有个User对象,其中有个status字段是枚举类型。当保存用户时,类型处理器的setParameter方法被调用,将枚举值转换成字符串存入数据库。查询用户时,getResult方法被调用,将数据库中的字符串重新转换成枚举。
整个过程对开发者是透明的。你只需要在配置中告诉MyBatis使用哪个类型处理器,剩下的转换工作就自动完成了。这种设计确实很优雅,把复杂的数据转换封装在专门的组件中。
类型处理器的注册通常通过配置文件完成,也可以在注解中指定。MyBatis会根据参数类型和返回值类型自动选择合适的处理器。当默认处理器不满足需求时,你就需要编写自己的实现了。
public class UserStatusTypeHandler extends BaseTypeHandler
@Override
public void setNonNullParameter(PreparedStatement ps, int i,
UserStatus parameter, JdbcType jdbcType) {
ps.setInt(i, parameter.getCode());
}
@Override
public UserStatus getNullableResult(ResultSet rs, String columnName) {
int code = rs.getInt(columnName);
return UserStatus.fromCode(code);
}
}