MybatisPlus配置自定义TypeHandler查询不生效

问题描述

我们在使用mybatis plus操作数据库的时候,经常会遇到在新增、修改、查询时,对某个字段进行自定义的一些操作,这样就不用在业务代码中写很多重复的逻辑,代码更加简洁。

这次我碰到一个需求,需要将数据库表中的手机号字段的数据进行加密,然后查询的时候进行解密。我直接想到了使用自定义TypeHandler在字段映射的时候进行拦截处理。

问题处理

我的代码是这样的:

java
复制代码
/** * 字段数据加解密类型处理器 */ public class FieldCipherTypeHandler extends BaseTypeHandler<String> { @Override public void setNonNullParameter(PreparedStatement ps, int i, String field, JdbcType jdbcType) throws SQLException { ps.setString(i, SM4Util.encryptData_ECB(field)); } @Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { String cipherText = rs.getString(columnName); return cipherText == null ? null : SM4Util.decryptData_ECB(cipherText); } @Override public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { String cipherText = rs.getString(columnIndex); return cipherText == null ? null : SM4Util.decryptData_ECB(cipherText); } @Override public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { String cipherText = cs.getString(columnIndex); return cipherText == null ? null : SM4Util.decryptData_ECB(cipherText); } }
java
复制代码
@Data @TableName("t_user") public class User implements Serializable { private static final long serialVersionUID = 1L; @TableId(value = "id", type = IdType.ASSIGN_UUID) private String id; @TableField(typeHandler = FieldCipherTypeHandler.class) private String phone; }
java
复制代码
public User getUserById(String userId){ User data = baseMapper.selectById(userId); } public User updateById(User user){ this.updateById(user); }

然后进行测试,但是我发现,修改的时候能正常将明文手机号转成密文并存储到表中,查询的时候并未进行解密操作,查出来的手机号还是密文

我配置了自定义类型转换器,但是查询的时候并未走我配置的转换器,在debug跟踪BaseTypeHandler.getResult(ResultSet rs, String columnName)看到还是走的StringTypeHandler ,说明查询的时候这个配置并未生效。

原因分析

  1. selectById 默认不解析 ResultMap
    MyBatis-Plus 的 selectById 默认使用自动映射(auto-mapping),可能跳过 TypeHandler 处理。
  2. 缺少 @TableName(autoResultMap = true)
    如果实体类没有显式声明 autoResultMap,查询时可能不会使用自定义 TypeHandler
  3. TypeHandler 未正确绑定到查询结果映射
    MyBatis 在查询时需要明确知道哪些字段需要特殊处理。

问题解决

在实体类的**@TableName**注解中加上配置:**autoResultMap = true **配置

java
复制代码
@Data @TableName(value = "t_user",autoResultMap = true) public class User implements Serializable { private static final long serialVersionUID = 1L; @TableId(value = "id", type = IdType.ASSIGN_UUID) private String id; @TableField(typeHandler = FieldCipherTypeHandler.class) private String phone; }

再次测试查询,配置生效,手机号被解密成了明文。

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
Kevin
下载 APP