Mybatis Plus 自定义数据类型处理

1.使用背景

针对未在源码中支持的数据结构,mybatis 提供类型转换接口TypeHandler供使用者实现,mybatis plus提供抽象类BaseTypeHandler实现TypeHandler接口,用户可自定义类型转换类,实现特殊数据结构转化、字段加解密等功能,本文采用AES加密算法加密用户密码。

2.TypeHandler接口源码解析

package org.apache.ibatis.type;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public interface TypeHandler {
    /**
     * 赋值语句
     * var1(sql语句对象),var2(参数位置),var3(参数值),var4(参数类型)
     */
    void setParameter(PreparedStatement var1, int var2, T var3, JdbcType var4) throws SQLException;
    /**
     * 取值语句
     * var1(sql结果集),var2(参数名称)
     */
    T getResult(ResultSet var1, String var2) throws SQLException;
    /**
     * 取值语句
     * var1(sql结果集),var2(参数位置)
     */
    T getResult(ResultSet var1, int var2) throws SQLException;
    /**
     * 取值语句
     * var1(sql可调用语句对象),var2(参数位置)
     */
    T getResult(CallableStatement var1, int var2) throws SQLException;
}

3.BaseTypeHandler类源码解析

ackage org.apache.ibatis.type;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.ibatis.executor.result.ResultMapException;
import org.apache.ibatis.session.Configuration;

public abstract class BaseTypeHandler extends TypeReference implements TypeHandler {
    /** @deprecated */
    @Deprecated
    protected Configuration configuration;

    public BaseTypeHandler() {
    }

    /** @deprecated */
    @Deprecated
    public void setConfiguration(Configuration c) {
        this.configuration = c;
    }

    public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
        if (parameter == null) {
            if (jdbcType == null) {
                throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");
            }

            try {
                ps.setNull(i, jdbcType.TYPE_CODE);
            } catch (SQLException var7) {
                throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. Cause: " + var7, var7);
            }
        } else {
            try {
                this.setNonNullParameter(ps, i, parameter, jdbcType);
            } catch (Exception var6) {
                throw new TypeException("Error setting non null for parameter #" + i + " with JdbcType " + jdbcType + " . Try setting a different JdbcType for this parameter or a different configuration property. Cause: " + var6, var6);
            }
        }

    }

    public T getResult(ResultSet rs, String columnName) throws SQLException {
        try {
            return this.getNullableResult(rs, columnName);
        } catch (Exception var4) {
            throw new ResultMapException("Error attempting to get column '" + columnName + "' from result set.  Cause: " + var4, var4);
        }
    }

    public T getResult(ResultSet rs, int columnIndex) throws SQLException {
        try {
            return this.getNullableResult(rs, columnIndex);
        } catch (Exception var4) {
            throw new ResultMapException("Error attempting to get column #" + columnIndex + " from result set.  Cause: " + var4, var4);
        }
    }

    public T getResult(CallableStatement cs, int columnIndex) throws SQLException {
        try {
            return this.getNullableResult(cs, columnIndex);
        } catch (Exception var4) {
            throw new ResultMapException("Error attempting to get column #" + columnIndex + " from callable statement.  Cause: " + var4, var4);
        }
    }
    
  /**
   * 代码已实现参数为null时的赋值取值操作,并提供抽象类涵盖非空参数值的取值赋值操作,开发者只需实现抽象类
   */

    public abstract void setNonNullParameter(PreparedStatement var1, int var2, T var3, JdbcType var4) throws SQLException;

    public abstract T getNullableResult(ResultSet var1, String var2) throws SQLException;

    public abstract T getNullableResult(ResultSet var1, int var2) throws SQLException;

    public abstract T getNullableResult(CallableStatement var1, int var2) throws SQLException;
}

4. AES加密工具类

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

/**
 * @ClassName AESUtils
 * @Description TODO
 * @Author SUSHENG
 * @Date 2021/5/29 13:48
 * @Version 1.0
 **/
public class AESUtils {
    /**
     * 密钥算法
     */
    private static final String ALGORITHM = "AES";
    /**
     * 加解密算法/工作模式/填充方式
     */
    private static final String ALGORITHM_STR = "AES/ECB/PKCS5Padding";

    /**
     * 秘密密钥
     */
    private static final String HEX_KEY = "*********";

    /**
     * AES加密
     *
     * @param data
     * @return
     */
    public static String encrypt(String data) {
        String result = data;
        try {
            SecretKeySpec key = new SecretKeySpec(HEX_KEY.getBytes(), ALGORITHM);
            Cipher cipher = Cipher.getInstance(ALGORITHM_STR);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            result = new BASE64Encoder().encode(cipher.doFinal(data.getBytes()));
        } catch (Exception e) {
            return result;
        }
        return result;
    }

    /**
     * AES解密
     *
     * @param base64Data
     * @return
     */
    public static String decrypt(String base64Data) {
        String result = base64Data;
        try {
            SecretKeySpec key = new SecretKeySpec(HEX_KEY.getBytes(), ALGORITHM);
            Cipher cipher = Cipher.getInstance(ALGORITHM_STR);
            cipher.init(Cipher.DECRYPT_MODE, key);
            result = new String(cipher.doFinal(new BASE64Decoder().decodeBuffer(base64Data)));
        } catch (Exception e) {
            return result;
        }
        return result;
    }
}

5.自定义类型转换

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @ClassName AESEncryptHandler
 * @Description TODO
 * @Author SUSHENG
 * @Date 2021/5/29 13:46
 * @Version 1.0
 **/
public class AESEncryptHandler extends BaseTypeHandler {
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, AESUtils.encrypt((String) parameter));
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String columnValue = rs.getString(columnName);
        return AESUtils.decrypt(columnValue);
    }

    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String columnValue = rs.getString(columnIndex);
        return AESUtils.decrypt(columnValue);
    }

    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex)
            throws SQLException {
        String columnValue = cs.getString(columnIndex);
        return AESUtils.decrypt(columnValue);
    }
}

6. 需转换字段配置

1.针对实体类字段,只需在该字段上增加typeHandler注解
@TableField(value="password",typeHandler= AESEncryptHandler.class)
private String password;
2.针对xml文件中resultMap中涉及字段
 

你可能感兴趣的:(Mybatis Plus 自定义数据类型处理)