首页 > 其他分享 >Mybatis自定义TypeHandler完成字段加解密And枚举数据处理

Mybatis自定义TypeHandler完成字段加解密And枚举数据处理

时间:2023-10-16 13:56:24浏览次数:34  
标签:String 自定义 TypeHandler 加解密 value user UserEnum public

Mybatis自定义TypeHandler完成字段加解密And枚举数据处理

新增And查询对枚举数据处理

定义枚举
@Getter
public enum UserEnum {

    HOLD_A_POST("在职", 10),
    RESIGN("离职", 20);

    private String name;

    private Integer value;
    
    UserEnum(String name, Integer value) {
        this.name = name;
        this.value = value;
    }

    /**
     * <P>根据状态码返回UserEnum对象</P>
     */
    public static UserEnum getEnumByValue(Integer value) {

        return switch (value) {
            case 10 -> HOLD_A_POST;
            case 20 -> RESIGN;
            default -> null;
        };
    }
}
处理对象User
  • 处理对象中包含UserEnum并给与默认值
@Data
public class User implements Serializable {

    @Serial
    private static final long serialVersionUID = 123456789L;

    private Long id;

    private Integer age;

    private String username;

    private String email;

    private String did;

    private Dept dept;

    private UserEnum userEnum =UserEnum.RESIGN;

}
UserMapp.xml
  • 以下解释在加解密字段时会用上

  • ResultMap标签中的查询映射字段age添加typeHandler ,在查询时对字段解密

    • typeHandler: 自定义ypeHandler的项目路径
  • #{user.age,typeHandler="com.unknown.c.MyUserEnumTypeHandler}在新增时对age字段加密

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.unknown.c.base.UserMapper">

    <resultMap id="userResultMapper" type="com.unknown.c.base.User">
        <result column="id" property="id"/>
        <result column="age" property="age" typeHandler="com.unknown.c.MyUserEnumTypeHandler"/>
        <result column="username" property="username"/>
        <result column="email" property="email"/>
        <result column="did" property="did"/>
        <result column="user_enum" property="userEnum"/>
    </resultMap>

    <select id="findById" resultMap="userResultMapper">
        select *
        from user u
        where id = ${id}
    </select>

    <insert id="InsertUserAndEnum" useGeneratedKeys="true" keyProperty="id">
        insert into user value (null, #{user.age,typeHandler="com.unknown.c.MyUserEnumTypeHandler}, #{user.username}, #			  				{user.email}, #{user.did},#{user.userEnum"})
      </insert>
</mapper>    
自定义TypeHandler
  • 处理User对象中的枚举类型
package com.unknown.c;

import com.unknown.c.base.UserEnum;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;

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

/**
 * @author unknown
 * @since 2023/10/15 15:40
 * TypeHandler<UserEnum>: TypeHandler处理的类型需要处理的类型
 */
public class MyUserEnumTypeHandler implements TypeHandler<UserEnum> {

    /**
     * <P>对枚举的处理</P>
     * @param ps PreparedStatement对象
     * @param i
     * @param userEnum 枚举参数
     * @param jdbcType jdbcType
     * @throws SQLException
     */
    @Override
    public void setParameter(PreparedStatement ps, int i, UserEnum userEnum, JdbcType jdbcType) throws SQLException {
        // 获取userEnum的value值
        ps.setString(i,userEnum.getValue().toString());
    }

    /**
     * <P>根据列名从返回结果中获取数据</P>
     * @param resultSet 返回结果
     * @param columnName 列名
     * @return UserEnum
     */
    @Override
    public UserEnum getResult(ResultSet resultSet, String columnName) throws SQLException {

        // 根据字段获取值
        int value = resultSet.getInt(columnName);
        return UserEnum.getEnumByValue(value);
    }

    /**
     * <P>根据索引从返回结果中获取数据</P>
     * @param resultSet 返回结果
     * @param columnIndex 索引
     * @return UserEnum
     */
    @Override
    public UserEnum getResult(ResultSet resultSet, int columnIndex) throws SQLException {
        int value = resultSet.getInt(columnIndex);
        System.out.println("从数据库获取的状态: " + value );
        return UserEnum.getEnumByValue(value);
    }

    /**
     * <P>从存储过程中获取数据</P>
     * @param cs 存储过程
     * @param columnIndex 索引
     * @return UserEnum
     */
    @Override
    public UserEnum getResult(CallableStatement cs, int columnIndex) {
        return null;
    }
}
注册自定义TypeHandler
  • properties配置文件

    • mybatis.type-handlers-package=com.unknown.c.MyUserEnumTypeHandler
      
  • yml配置文件

    • mybatis:
        type-handlers-package: com.unknown.c.MyUserEnumTypeHandler
      
  • mybatis-config.xml配置文件

    • <typeHandlers>
          <typeHandler handler="com.unknown.c.MyUserEnumTypeHandler" javaType="com.unknown.c.base.UserEnum"/>
      </typeHandlers>
      
测试结果
  • 新增

    @Test
    public void InsertUserAndEnumTest() throws IOException {
    
        // 读取Mybatis配置文件
        InputStream resourceAsStream = getResourceAsStream("mybatis-config.xml");
        // 构建SqlSessionFactorBean对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        // 获取SqlSession.设置自动提交数据
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        // 获取Mapper接口对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setAge(11);
        user.setUsername("111");
        user.setEmail("1111");
        user.setDid("1");
        /**
         * 如不自定义TypeHandler,数据库中存储的将是 HOLD_A_POST 化的字符串
         * 如果将User中的 UserEnum 枚举变为Long或者int类型,可以 user.setUserEnum(UserEnum.HOLD_A_POST.getValue()).但UserEnum必须有get方法
         */
        user.setUserEnum(UserEnum.HOLD_A_POST);
        mapper.InsertUserAndEnum(user);
        System.out.println("数据库中自增的ID:"+user.getId());
    
    }	
    
  • 结果验证

    • 如下图所示,红色框框中的是在没有对枚举字段进行处理,在新增中直接添加到是HOLD_A_POST化的字符串
    • 橘色框框中的是自定义TypeHandle后,在TypeHandle取出枚举的value进行存储

  • 查询

    @Test
    public void findByIdTest() throws IOException {
    
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User byId = mapper.findById(50);
        System.out.println("统计当前用户ID=2: "+byId);
    }
    
  • 结果验证

    • 在下图所示,ID=50的数据在数据库中是10,对应的枚举字段HOLD_A_POST,图片显示RESIGN是笔者出了个bug。现笔记已修复。不影响此段笔记的正常使用

总结
  • 笔者突发奇想,在小型项目(例如自己的博客网站)中,完全可以使用枚举代替数据字典。

字段加解密
自定义TypeHandler
  • 笔者在此并没有做什么加密操作,只是拿到字段做了一个字符串拼接。
package com.unknown.c;

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

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

/**
 * <P>自定义TypeHandler完成加解密</P>
 * @author unknown
 * @since 2023/10/16 11:05
 * TypeHandler<String>: 处理String类型的字段
 */
public class MyTypeHandlerEncryption implements TypeHandler<String> {
    @Override
    public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        String username="加密字段"+parameter;
        ps.setString(i,username);
    }

    @Override
    public String getResult(ResultSet rs, String columnName) throws SQLException {
        String string = rs.getString(columnName)+"解密字段";
        return string;
    }

    @Override
    public String getResult(ResultSet rs, int columnIndex) throws SQLException {
        return null;
    }

    @Override
    public String getResult(CallableStatement cs, int columnIndex) throws SQLException {
        return null;
    }
}
注册自定义TypeHandler
  • properties配置文件

    • mybatis.type-handlers-package=com.unknown.c.MyTypeHandlerEncryption
      
  • yml配置文件

    • mybatis:
        type-handlers-package: com.unknown.c.MyTypeHandlerEncryption
      
  • mybatis-config.xml配置文件

    • <typeHandlers>
          <typeHandler handler="com.unknown.c.MyTypeHandlerEncryption"/>
      </typeHandlers>
      
UserMapper.xml
  • typeHandler="com.unknown.c.MyUserEnumTypeHandler": 查询时解密
  • typeHandler=com.unknown.c.MyTypeHandlerEncryption: 新增是加密
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.unknown.c.base.UserMapper">

    <resultMap id="findByIdEncryptionMap" type="com.unknown.c.base.User">
        <result column="id" property="id"/>
        <result column="age" property="age"/>
        <result column="username" property="username" typeHandler="com.unknown.c.MyTypeHandlerEncryption"/>
        <result column="email" property="email"/>
        <result column="did" property="did"/>
        <result column="user_enum" property="userEnum"/>
    </resultMap>

    <select id="findByIdEncryption" resultMap="findByIdEncryptionMap">
        select  id,age,username,email,did,user_enum
        from user u
        where id = ${id}
    </select>

    <insert id="insertEncryption" useGeneratedKeys="true" keyProperty="id">
     insert into user value (null,
                            #{user.age},
                            #{user.username,typeHandler=com.unknown.c.MyTypeHandlerEncryption},
                            #{user.email},
                            #{user.did},
                            #{user.userEnum})
    </insert>
</mapper>
新增代码
/**
 * <P>新增加密测试</P>
 * 参阅: {@link MyTypeHandlerEncryption}
 */
@Test
public void insertEncryption() throws IOException {
    // 读取Mybatis配置文件
    InputStream resourceAsStream = getResourceAsStream("mybatis-config.xml");
    // 构建SqlSessionFactorBean对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
    // 获取SqlSession.设置自动提交数据
    SqlSession sqlSession = sqlSessionFactory.openSession(true);
    // 获取Mapper接口对象
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    User user = new User();
    user.setAge(11);
    user.setUsername("111");
    user.setEmail("1111");
    user.setDid("1");
    user.setUserEnum(UserEnum.HOLD_A_POST);
    mapper.insertEncryption(user);
    System.out.println("数据库中自增的ID:"+user.getId());
}
  • 添加结果

    • 在控制台中可以看到TypeHandler成功的执行

查询代码
/**
 * <P>查询解密测试</P>
 * @throws IOException
 */
@Test
public void findByIdEncryption() throws IOException {

    InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
    SqlSession sqlSession = sqlSessionFactory.openSession(true);
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    User byId = mapper.findByIdEncryption(51);
    System.out.println("统计当前用户ID=50: "+byId);
}
  • 查询结果

    • 成功的改变了原本的数据,但数据库中的字段值并没有变

总结
  • 相对于这种加解密方法,笔者更喜欢Jackson的注解式,更加灵活多变,不使用不加注解就行,而实现MybatisTypeHandler,每次都需要再SQLResultMap映射上添加,有很大的误伤可能

标签:String,自定义,TypeHandler,加解密,value,user,UserEnum,public
From: https://www.cnblogs.com/ChenQ2/p/17767181.html

相关文章

  • 学习C语言心得-自定义函数-每调用一次函数 num的值+1
    每调用一次函数num的值+1#include<stdio.h>NUM(int*num){ (*num)++;}intmain(){ intnum=0; NUM(&num); printf("%d\n",num); NUM(&num); printf("%d\n",num); NUM(&num); printf("%d\n",num); NUM(&num)......
  • 学习C语言心得-自定义函数-对整形有序数组进行二分查找-二分法
    对整形有序数组进行二分查找#include<stdio.h>intfind(intarr[],intsz,intk){ intleft=0;intright=sz-1; while(left<=right) { intmid=left+right/2; if(k>arr[mid]) { left=mid+1; } if(k<arr[mid]) { right=mid......
  • 学习C语言心得-自定义函数 输入两个数字求和
    输入两个数字求和#include<stdio.h>intsum(inta,intb){ returna+b;}intmain(){ inta=0; intb=0; printf("请输入ab的值:"); scanf("%d%d",&a,&b); intSum=sum(a,b); printf("Sum=%d",Sum); return0;}运行......
  • 学习C语言心得-运用自定义函数求素数
    自定义函数求素数#include<stdio.h>intpanduan(inta){ inti=0; for(i=2;i<a;i++) { if(a%i==0) { returna; } } return0;}intmain(){ intnumber=0; printf("请输入一个数:"); scanf("%d",&number); int......
  • hive大数据测试(时间数据清洗UDF打包到hive中调用自定义函数,hive表数据导出到本机)
    1.数据清洗pom依赖:<properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding&......
  • iOS 17.1 Beta 3上线:iPhone 15 Pro自定义操作按钮误触问题修复了
    在iPhone15Pro和iPhone15ProMax上,苹果将静音拨片重新设计为自定义操作按钮,支持一键启用各种操作。在系统中选定你要用的快捷功能后,按住此操作按钮即可启动相应的操作,比如静音模式、专注模式、相机、手电筒、语音备忘录、翻译、放大器、快捷指令以及辅助功能等等。尽管操作......
  • hashcat charsets文件夹下 .hcchr自定义字符集
    说明通常我们使用的是英文字符,abc123这些,但是如果遇到俄文、阿拉伯等一些非ASCII码的字符集,每次手动输入不现实。所以就可以保存到.hcchr文件中一、先看看,hashcat提供內建字符集?l=abcdefghijklmnopqrstuvwxyz?u=ABCDEFGHIJKLMNOPQRSTUVWXYZ?d=0123456789?s=......
  • 使用api调用chatGPT,python自定义接口方法
    用非官网的api一般要把官网地址https://api.openai.com/改为相应网站的url。今天测试的时候找了各种教程都没什么用,最后终于成功了,代码如下:importopenaiimportjsonimportosopenai.api_key="sk-xxxxxxxxxx"#改成你的keyopenai.api_base="https://yyyyyyyyyy/v1"#改成......
  • 直播平台搭建,自定义View实现loading动画加载
    直播平台搭建,自定义View实现loading动画加载先自定义一个View,继承自LinearLayout,在Layout中,添加布局控件 /** *Createdbyxiedongon2017/3/7. */ publicclassLoading_viewextendsLinearLayout{  privateContextmContext;  privateRelativeLayoutloadi......
  • FlashDuty Changelog 2023-09-21 | 自定义字段和开发者中心
    FlashDuty:一站式告警响应平台,前往此地址免费体验!自定义字段FlashDuty已支持接入大部分常见的告警系统,我们将推送内容中的大部分信息放到了Lables进行展示。尽管如此,我们用户还是会有一些扩展或定制性的需求,比如人工标记一个故障是否为误报。因此我们提供了自定义字段功能,......