mybatis的typehandler是实现敏感字段自动加解密的核心机制,通过继承basetypehandler重写setnonnullparameter(入库加密)和getnullableresult(出库解密),配合aes等算法与spring配置注入密钥,可做到业务无感、全局透明;同时支持枚举按code映射、泛型复用及mybatis-plus注解式指定。

MyBatis 的 TypeHandler 是处理 Java 类型与 JDBC 类型之间转换的核心机制,自定义它能干净地解决敏感字段加密/解密、枚举序列化等场景,避免在业务逻辑中到处写加解密代码。
一、加密敏感字段:比如手机号、身份证号自动加解密
目标是:写入数据库前自动加密,查询时自动解密,对业务层完全透明。
- 实现
BaseTypeHandler<string></string>,重写setNonNullParameter(存)和getNullableResult(取) - 加密建议用 AES(需统一密钥和 IV),避免硬编码密钥,可从 Spring 环境或配置中心注入
- 注意:数据库字段类型应为
VARCHAR或TEXT,加密后是 Base64 字符串 - 注册方式推荐在
@MapperScan中指定typeHandlersPackage,或在mybatis-config.xml中全局注册
示例简写:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
private final Cipher encryptCipher;
private final Cipher decryptCipher;
public EncryptedStringTypeHandler(Cipher encryptCipher, Cipher decryptCipher) {
this.encryptCipher = encryptCipher;
this.decryptCipher = decryptCipher;
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String s, JdbcType jdbcType) throws SQLException {
String encrypted = Base64.getEncoder().encodeToString(encryptCipher.doFinal(s.getBytes()));
ps.setString(i, encrypted);
}
@Override
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
String encrypted = rs.getString(columnName);
return encrypted == null ? null : new String(decryptCipher.doFinal(Base64.getDecoder().decode(encrypted)));
}
}
二、枚举类型:映射成数据库中的字符串或数字
默认 MyBatis 对枚举只支持 EnumTypeHandler(存 name)和 EnumOrdinalTypeHandler(存 ordinal),但实际常需按自定义字段(如 code)存取。
- 让枚举实现一个接口(如
CodeEnum<t></t>),含getCode()和ofCode(T)方法 - TypeHandler 中通过反射或静态 map 缓存枚举实例,避免每次调用
valueOf报错 - 在
@Results或<resultmap></resultmap>中显式指定该 TypeHandler,或用@MappedTypes+@MappedJdbcTypes自动绑定 - 若多个枚举共用同一套逻辑,可用泛型 TypeHandler(如
GenericEnumTypeHandler<e extends codeenum></e>)
三、使用技巧与注意事项
- 不要在 TypeHandler 中做耗时操作(如远程调用、IO),它在每行数据映射时执行
- 加解密类(如 Cipher)建议单例复用,避免重复初始化开销
- 测试时务必覆盖 null 值、空字符串、异常输入(如损坏的密文、非法枚举 code)
- 如果用了 MyBatis-Plus,可通过
@TableField(typeHandler = XXX.class)指定单个字段;原生 MyBatis 可在<result></result>或<parameter></parameter>标签里写typeHandler="xxx"
四、Spring Boot 中更简洁的注册方式
在配置类中声明 Bean,并用 @ConfigurationProperties 注入密钥,再通过 Configuration.addTypeHandler(...) 注册,比 XML 更灵活可控。也可配合 @Mapper 接口上的 @Options(defaultStatementTimeout = ...) 等做细粒度控制。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










