一、TypeHandler概述
二、TypeHandler的工作原理
TypeHandler在MyBatis中是一个核心概念,其工作原理主要涉及Java类型和JDBC类型之间的转换。下面将详细介绍TypeHandler的工作原理。
1.设置参数(Parameter Setting)
当Mybatis要执行一个sql语句时,(例如INSERT UPDATE等),它需要将Java对象的属性值设置到SQL语句对应的占位符上,这个过程就是通过TypeHandler来完成的。
具体步骤
2.获取结果(Result Getting)
当数据库进行查询操作并返回结果集合时,MyBatis需要将结果集中的数据提取出来,转换成Java对象中的对应属性类型,这个过程同样是由TypeHandler来完成的。
具体步骤
- MyBatis会根据映射配置找到对应的TypeHandler实例
- TypeHandler实例会从ResultSet对象中提取数据,这个提取过程是根据数据库字段和Java属性之间的映射关系来实现的。
- 提取出来的数据会被转换成Java对象中的对应属性类型,这个转换过程是由Java类型和JDBC类型之间的映射关系来完成的。
- 转换后的值会被设置到Java对象中对应的属性上,以便程序能够正确处理和使用这些数据。
3.类型映射和转换规则
TypeHandler的核心功能是实现Java类型和JDBC类型之间的映射和转换。这个映射和转换规则是根据Java类型和JDBC类型的特性和语义来定义的。
对于基本数据类型(如int、long、float等),MyBatis提供了内置的TypeHandler实现,这些实现能够直接将Java基本数据类型转换为对应的JDBC基本数据类型,反之亦然。
对于复杂数据类型(如自定义对象、集合等),MyBatis允许开发者自定义TypeHandler来实现复杂的类型转换逻辑。
4.自定义TypeHandler的扩展性
MyBatis的TypeHandler机制具有很高的扩展性。我们可以通过实现TypeHandler接口或继承BaseTypeHandler类来创建自定义的TypeHandler实现。自定义的TypeHandler可以实现任意复杂的类型转换逻辑,以满足特定业务需求。
此外,MyBatis还提供了丰富的API和扩展点来支持开发者自定义TypeHandler的注册和使用方式。我们可以通过配置文件、注解或编程方式将自定义的TypeHandler注册到MyBatis中,并在Mapper的XML映射文件中引用它们来处理特定的数据类型转换需求。
三、自定义的具体实现
业务场景
现在我们要对用户存入的手机号进行处理。存入手机号时需要进行加密操作,从数据库中取出手机号时,进行解密。
分析需求
TypeHandler是将指定类型转换成数据库支持的类型
- TypeHandler拿到手机号,进行加密
- TypeHandler加密后转换成指定JDBC类型存入数据库
- TypeHandler从数据库中取出JDBC类型
- TypeHandler拿到JDBC类型进行解密
- 返回手机号
具体实现
我们先定义一个Encrypt类。
这是我们自定义的类,后续会配合注解使用。
@Data
public class Encrypt {
private String value;
public Encrypt(){}
public Encrypt(String value){
this.value = value;
}
}
@MappedTypes(Encrypt.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class EncryptTypeHandler extends BaseTypeHandler<Encrypt> {
private final byte[] KEY = "1234567abcdefg".getBytes(StandardCharsets.UTF_8);
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Encrypt parameter, JdbcType jdbcType) throws SQLException {
if(parameter == null || parameter.getValue() == null){
ps.setString(i,null);
return;
}
AES aes = new AES(KEY);
String str = aes.encryptHex(parameter.getValue());
ps.setString(i, str);
}
@Override
public Encrypt getNullableResult(ResultSet rs, String columnName) throws SQLException {
return decrypt(rs.getString(columnName));
}
@Override
public Encrypt getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return decrypt(rs.getString(columnIndex));
}
@Override
public Encrypt getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return decrypt(cs.getString(columnIndex));
}
private Encrypt decrypt(String str){
if (StringUtils.hasText(str)){
return null;
}
return new Encrypt(SecureUtil.aes(KEY).decryptStr(str));
}
}
注意
在properties文件中配置路径
mybatis.type-handlers-package=com.example.lottery.dao.handler