package com.artfess.base.handler;


import com.artfess.base.util.CryptoUtil;
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;

/**
 * 加密解密类型处理器，此类只针对字符串进行加密，如有其他类型加密可自定义添加处理类或者将处理类改为泛型，根据不同数据类型进行不同的处理
 * 使用说明：不同的使用场景都可以使用，例如实体注解、自定义sql xml映射、注解SQL插入数据加密、查询数据解密等等
 * 1.实体注解：直接在实体或者VO上使用注解进行加解密，示例如下：
 *   @TableField(value = "PHONE_NUM", typeHandler = AesTypeHandler.class)
 *   private String phoneNum;
 * 2.使用注解形式插入数据加密，示例如下：
 *   @Insert("INSERT INTO encrypt_demo (ID, USER_NAME, PHONE_NUM, PASS_WORD, AGE_) VALUES (#{vo.id},#{vo.userName},#{vo.phoneNum,typeHandler=com.wts.encryptdemo.base.handle.AesTypeHandler},#{vo.passWord,typeHandler=com.wts.encryptdemo.base.handle.AesTypeHandler},#{vo.age})")
 *   void insertVo(@Param("vo") EncryptDemoVo vo);
 * 3.使用注解形式查询数据解密，示例如下：
 *   @Results(id ="encrypt", value = {
 *       @Result(column = "PASS_WORD", property = "passWord", typeHandler = AesTypeHandler.class),
 *       @Result(column = "PHONE_NUM", property = "phoneNum", typeHandler = AesTypeHandler.class)
 *   })
 *   @Select("SELECT * FROM encrypt_demo WHERE ID = #{id}")
 *   EncryptDemoVo selectVoById(Long id);
 * 4.自定义SQL或者XML映射查询数据解密，示例如下：
 *     <resultMap id="BaseResultMap" type="com.wts.encryptdemo.base.vo.EncryptDemoVo">
 *         <id column="ID" property="id" />
 *         <result column="USER_NAME" property="userName" />
 *         <result column="PHONE_NUM" property="phoneNum" typeHandler="com.wts.encryptdemo.base.handle.AesTypeHandler"/>
 *         <result column="PASS_WORD" property="passWord" typeHandler="com.wts.encryptdemo.base.handle.AesTypeHandler"/>
 *         <result column="AGE_" property="age" />
 *     </resultMap>
 *
 *     <select id="getDemo" resultMap="BaseResultMap">
 *         select * from encrypt_demo where id = #{id}
 *     </select>
 * 5.QueryWrapper操作数据加解密，直接配合第一点注解使用，自动加解密
 *
 *
 */
public class AesTypeHandler extends BaseTypeHandler<String> {
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, CryptoUtil.encrypt(parameter));
    }

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

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

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

