美文网首页
Mybatis Plus 自定义数据类型处理

Mybatis Plus 自定义数据类型处理

作者: lovefy | 来源:发表于2022-11-23 15:13 被阅读0次

    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<T> {
        /**
         * 赋值语句
         * 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<T> extends TypeReference<T> implements TypeHandler<T> {
        /** @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中涉及字段
     <result column="DS_PASSWORD" jdbcType="VARCHAR" property="dsPassword" typeHandler="....AESEncryptHandler"/>
    

    相关文章

      网友评论

          本文标题:Mybatis Plus 自定义数据类型处理

          本文链接:https://www.haomeiwen.com/subject/rkfaxdtx.html