利用Mybatis的TypeHandler实现字段加密

本文介绍了如何在Springboot应用中,利用Mybatis的TypeHandler功能配合AES加密工具类,实现实体类字段的加密和解密操作,以及如何在实体类上添加注解进行自动处理。

利用MybatisTypeHandler实现字段加密

引言

记录使用MybatisTypeHandler实现对实体类字段的加密.

版本

  • Springboot 2.5.3

  • MybatisPlus 3.4.2

  • Mysql 5.4.7

AES工具类

编写一个工具类,实现对数据的加解密操作.

public class AesUtils {
   
   

    public static final String AES_MIDDLE_KEY = "chenZhiLing";

    //aes的key
    private static Key AES_KEY;


    public static String encryptByAes(String content) {
   
   
        if(ObjectUtils.isEmpty(content)){
   
   
            return null;
        }
        try {
   
   
            // 加密
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, getKey());
            byte[] result = cipher.doFinal(content.getBytes());
            return org.apache.commons.codec.binary.Base64.encodeBase64String(result);
        } catch (Exception e) 
<think>好的,我现在需要在MyBatis的XML配置中处理单一字段返回时的类型转换,使用typeHandler。让我先回忆一下MyBatis的相关知识。 首先,TypeHandler的作用是处理Java类型和数据库类型之间的转换。比如,数据库中的日期和Java的Date类型转换,或者像加解密这样的自定义处理。根据引用[4]提到的TypeHandler接口,它有几个方法,主要是在设置参数和获取结果时进行类型转换。 用户的问题是在返回单一字段时如何正确使用typeHandler。通常,在查询结果映射中,如果是单个字段,可能会直接返回基本类型或者某个对象,但这里可能需要指定TypeHandler来处理这个字段的值。 比如,假设有一个字段需要解密,数据库中存储的是加密后的字符串,返回时需要解密成明文。这时就需要在resultMap中指定该字段使用自定义的TypeHandler。根据引用[3]的例子,他们配置了AesTypeHandler来处理加解密,可能是在字段映射时用typeHandler属性指定。 但用户的情况是单一字段返回,可能没有使用resultMap,而是直接返回基本类型。比如,直接返回一个String或者Integer。这时候,如何应用TypeHandler呢? 可能需要查看MyBatis的文档,当使用select语句返回单一字段时,是否可以在resultType中指定类型,并且通过某种方式关联TypeHandler。或者,可能需要显式地定义resultMap,即使只有一个字段,然后在resultMap中指定typeHandler。 比如,假设查询一个加密字段name,返回解密后的字符串。可以创建一个resultMap,指定该字段typeHandler为自定义的AesTypeHandler。然后在XML中使用这个resultMap作为结果映射。 根据引用[2],DateTypeHandler用于处理日期类型,可能在字段映射时通过jdbcType和typeHandler属性来指定。所以,同样的逻辑,单一字段的返回也需要在resultMap中定义,并指定typeHandler。 如果用户直接在select标签中使用resultType="java.lang.String",而没有resultMap,那么可能需要其他方式来应用TypeHandler。但MyBatis在这种情况下可能无法自动应用TypeHandler,除非在配置中全局注册了该TypeHandler,并且Java类型和JDBC类型匹配。但全局注册可能不够灵活,特别是当同一个类型需要不同的处理时。 所以,正确的做法应该是定义一个resultMap,即使只有一个字段,然后在其中指定typeHandler。例如: <resultMap id="nameResult" type="java.lang.String"> <result property="value" column="name" typeHandler="com.example.AesTypeHandler"/> </resultMap> 但这里有个问题,因为当映射到java.lang.String时,property应该是空吗?或者是否需要使用构造方法?可能需要进一步确认MyBatis的文档。 另一种情况,如果返回的是一个对象,但该对象只有一个属性,那么resultMap中的property对应到该属性。但用户的情况是单一字段返回,可能直接返回基本类型,这时候可能需要用resultMap来包装。 或者,在select语句中,可以直接在字段上指定typeHandler。例如: <select id="getName" resultType="java.lang.String"> SELECT name AS "value" <typeHandler handler="com.example.AesTypeHandler"/> </select> 不过MyBatis的语法是否支持在字段级别直接指定typeHandler呢?根据引用[4],TypeHandler通常在resultMap的result元素中指定,或者在参数处理时指定。所以可能需要通过resultMap来应用。 因此,正确的步骤应该是: 1. 定义自定义TypeHandler实现TypeHandler接口或继承BaseTypeHandler。 2.MyBatis的配置文件中注册该TypeHandler,或者在XML映射文件中局部引用。 3. 在resultMap中,为对应的字段指定typeHandler属性。 4. 在select语句中使用该resultMap作为结果映射。 例如,在XML中: <resultMap id="decryptedNameMap" type="java.lang.String"> <result column="name" jdbcType="VARCHAR" typeHandler="com.example.AesTypeHandler"/> </resultMap> <select id="selectName" resultMap="decryptedNameMap"> SELECT name FROM users WHERE id = #{id} </select> 这样,当查询返回name字段时,会使用AesTypeHandler进行处理,将数据库中的加密值转换为明文字符串。 如果用户不想定义resultMap,是否有其他方式?比如在resultType中使用别名,并在字段上应用typeHandler。例如: <select id="selectName" resultType="java.lang.String"> SELECT name AS value <typeHandler ...> </select> 但MyBatis可能不支持这种写法。因此,使用resultMap可能是更可靠的方式。 另外,根据引用[1],MyBatis有默认的TypeHandler,但如果需要自定义,必须正确注册。比如,在mybatis-config.xml中配置typeHandlers,或者在Spring Boot中通过配置类注册。例如引用[3]中的配置方式。 总结步骤: 1. 创建自定义TypeHandler类,处理目标类型的转换。 2. 在配置文件中注册该TypeHandler,或者在XML映射文件中直接指定全限定类名。 3. 在resultMap中为字段指定typeHandler属性。 4. 在select语句中引用该resultMap。 这样就能正确应用TypeHandler处理单一字段的返回类型转换了。</think>在MyBatis中为单一字段返回值配置`TypeHandler`需通过`resultMap`明确指定类型处理器。以下是具体步骤: --- ### 1. 定义自定义TypeHandler 继承`BaseTypeHandler`或实现`TypeHandler`接口,例如处理加密字段的`AesTypeHandler`: ```java public class AesTypeHandler extends BaseTypeHandler<String> { @Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, encrypt(parameter)); // 加密后存入数据库 } @Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { return decrypt(rs.getString(columnName)); // 解密查询结果 } // 其他重写方法... } ``` --- ### 2. 注册TypeHandler #### 方式一:全局注册(mybatis-config.xml) ```xml <typeHandlers> <typeHandler handler="com.example.AesTypeHandler"/> </typeHandlers> ``` #### 方式二:Spring Boot配置 在`application.yml`中指定扫描包: ```yaml mybatis: type-handlers-package: com.example.handlers ``` --- ### 3. 配置XML映射文件 #### 定义resultMap ```xml <resultMap id="singleFieldResult" type="java.lang.String"> <result column="encrypted_field" jdbcType="VARCHAR" typeHandler="com.example.AesTypeHandler"/> </resultMap> ``` #### 查询语句引用resultMap ```xml <select id="getEncryptedData" resultMap="singleFieldResult"> SELECT encrypted_field FROM table WHERE id = #{id} </select> ``` --- ### 4. 直接指定typeHandler(简化场景) 若字段直接映射到Java基本类型,可通过`resultType`结合别名强制指定: ```xml <select id="getData" resultType="java.lang.String"> SELECT encrypted_field AS "value" <!-- 显式声明typeHandler --> <result column="value" typeHandler="com.example.AesTypeHandler"/> </select> ``` --- ### 关键点说明 - **必须使用resultMap**:单一字段返回时,MyBatis默认无法自动匹配`TypeHandler`,需通过`resultMap`显式声明[^4]。 - **类型匹配**:确保`TypeHandler`处理的Java类型与返回值类型(如`java.lang.String`)一致[^1]。 - **作用域优先级**:局部XML中直接指定的`typeHandler`会覆盖全局配置[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值