Mybatis的TypeHandler實(shí)現(xiàn)數(shù)據(jù)加解密詳解
一、背景
有些項(xiàng)目需要對一些信息入庫前進(jìn)行加密處理,為了數(shù)據(jù)安全或者隱私合規(guī),但與此同時(shí)也使數(shù)據(jù)處理變得麻煩,不可避免的會帶來重復(fù)冗長的代碼。如果能在持久層處理好數(shù)據(jù),避免在業(yè)務(wù)層處理,就能合理的規(guī)避這個問題。
二、方案
使用mybatis框架提供的TypeHandler來實(shí)現(xiàn)在持久層處理數(shù)據(jù)。
TypeHandler簡介
Typehandler是mybatis提供的一個接口,通過實(shí)現(xiàn)這個接口,可以實(shí)現(xiàn)jdbc類型數(shù)據(jù)和java類型數(shù)據(jù)的轉(zhuǎn)換,我們??吹降膙archar轉(zhuǎn)string、bigint轉(zhuǎn)long等都是mybatis自身實(shí)現(xiàn)此接口處理的。

我們可以自己實(shí)現(xiàn)一個Typehandler,滿足自己的需求。
三、詳細(xì)實(shí)現(xiàn)
1.實(shí)現(xiàn)接口,定義自己的Typehandler
一般實(shí)現(xiàn)BaseTypeHandler接口即可。筆者的加解密使用了hutool提供的des加密,maven坐標(biāo)如下:
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.10</version>
</dependency>代碼如下,可根據(jù)業(yè)務(wù)需求編寫方法實(shí)現(xiàn)代碼:
package com.example.cryptotypehandler.common;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@Slf4j
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(String.class)
public class CryptoTypeHandler extends BaseTypeHandler<String> {
private final byte[] key = {-26, -70, -29, -99, 73, -82, 91, -50, 79, -77, 59, 104, 2, -36, 50, -22, -39, -15, -57, -89, 81, -99, 42, -89};
private final SymmetricCrypto des = new SymmetricCrypto(SymmetricAlgorithm.DESede, key);
/*
* 加工入?yún)?
*/
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
if (parameter != null) {
//加密
String encryptHex = des.encryptHex(parameter);
log.info("{} ---加密為---> {}", parameter, encryptHex);
ps.setString(i, encryptHex);
}
}
/*
* 根據(jù)列名獲取返回結(jié)果,可在此方法中加工返回值
*/
@Override
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
String originRes = rs.getString(columnName);
if (originRes != null) {
String res = des.decryptStr(originRes);
log.info("{} ---解密為---> {}", originRes, res);
return res;
}
log.info("結(jié)果為空,無需解密");
return null;
}
/*
* 根據(jù)列下標(biāo)獲取返回結(jié)果,可在此方法中加工返回值
*/
@Override
public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String originRes = rs.getString(columnIndex);
if (originRes != null) {
String res = des.decryptStr(originRes);
log.info("{} ---解密為---> {}", originRes, res);
return res;
}
log.info("結(jié)果為空,無需解密");
return null;
}
/*
* 根據(jù)列下標(biāo)獲取返回結(jié)果(存儲過程),可在此方法中加工返回值
*/
@Override
public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String originRes = cs.getString(columnIndex);
if (originRes != null) {
String res = des.decryptStr(originRes);
log.info("{} ---解密為---> {}", originRes, res);
return res;
}
log.info("結(jié)果為空,無需解密");
return null;
}
}2.注冊自定義的TypeHandler
編寫好的TypeHandler需要注冊到mybatis中,在application.yml或者application.properties中加入配置:
properties文件:
mybatis.type-handlers-package=com.example.cryptotypehandler.common
yml文件
mybatis: type-handlers-package: com.example.cryptotypehandler.common
筆者包結(jié)構(gòu)如下

3.定義mapper層接口
實(shí)體對象類
package com.example.cryptotypehandler.domain;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class AccountDO {
private Long id;
/**
* 用戶名
*/
private String userName;
/**
* 密碼
*/
private String password;
}和普通的mapper沒區(qū)別:
package com.example.cryptotypehandler.mapper;
import com.example.cryptotypehandler.domain.AccountDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author shuai.mh
* @since 2022-11-29
*/
@Mapper
public interface AccountMapper {
int insertEncrypt(AccountDO accountDO);
List<AccountDO> selectAccount(AccountDO accountDO);
}4.編寫mapper.xml
這邊有幾個注意點(diǎn):
- 首先看insert語句,我們需要加密的是password字段,因此在password后加上typeHandler=com.example.cryptotypehandler.common.CryptoTypeHandler;此外,#{userName}中,jdbcType=varchar不要填寫,因?yàn)樽远x的typerHandler中加了下面兩個注解:@MappedJdbcTypes(JdbcType.VARCHAR)和@MappedTypes(String.class),這兩個注解表示JdbcType為varchar是會使用此handler,加了的話,userName也會被加密。
- 再看select語句,sql和普通的沒有區(qū)別,但是resultMap中的password映射加了typeHandler="com.example.cryptotypehandler.common.CryptoTypeHandler",代表此字段在轉(zhuǎn)換成實(shí)體對象時(shí)會被handler處理,此外其他字段的映射jdbcType保持缺省,如果是varchar也會被處理。
<?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.example.cryptotypehandler.mapper.AccountMapper">
<!-- 通用查詢映射結(jié)果 -->
<resultMap id="BaseResultMap" type="com.example.cryptotypehandler.domain.AccountDO">
<id column="id" property="id" />
<result column="user_name" property="userName"/>
<result column="password" property="password" typeHandler="com.example.cryptotypehandler.common.CryptoTypeHandler" />
</resultMap>
<!-- 通用查詢結(jié)果列 -->
<sql id="Base_Column_List">
id, user_name, password
</sql>
<insert id="insertEncrypt">
insert into account (id, user_name, password)
values (#{id}, #{userName}, #{password, typeHandler=com.example.cryptotypehandler.common.CryptoTypeHandler})
</insert>
<select id="selectAccount" resultMap="BaseResultMap">
select <include refid="Base_Column_List"></include>
from account
where user_name = #{userName}
</select>
</mapper>5.調(diào)用接口,簡單測試
①新增用戶

②查看數(shù)據(jù)庫,密碼已被加密

③查詢用戶,查詢結(jié)果已解密

到此這篇關(guān)于Mybatis的TypeHandler實(shí)現(xiàn)數(shù)據(jù)加解密詳解的文章就介紹到這了,更多相關(guān)TypeHandler數(shù)據(jù)加解密內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- MyBatis自定義TypeHandler實(shí)現(xiàn)字段加密解密
- MyBatis類型處理器TypeHandler的作用及說明
- MyBatis中TypeHandler的使用教程詳解
- MyBatis-Plus?中?typeHandler?的使用實(shí)例詳解
- SpringBoot中MyBatis使用自定義TypeHandler的實(shí)現(xiàn)
- 解決Mybatis-plus自定義TypeHandler查詢映射結(jié)果一直為null問題
- Mybatis中TypeHandler使用小結(jié)
- Mybatis中自定義TypeHandler處理枚舉的示例代碼
- MyBatisPlus自定義JsonTypeHandler實(shí)現(xiàn)自動轉(zhuǎn)化JSON問題
- MyBatis自定義TypeHandler如何解決字段映射問題
- MyBatis中TypeHandler基本用法與示例
相關(guān)文章
IDEA2020.1啟動SpringBoot項(xiàng)目出現(xiàn)java程序包:xxx不存在
這篇文章主要介紹了IDEA2020.1啟動SpringBoot項(xiàng)目出現(xiàn)java程序包:xxx不存在,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
SpringBoot+WebSocket實(shí)現(xiàn)消息推送功能
WebSocket協(xié)議是基于TCP的一種新的網(wǎng)絡(luò)協(xié)議。本文將通過SpringBoot集成WebSocket實(shí)現(xiàn)消息推送功能,感興趣的可以了解一下2022-08-08
Mybatis-Plus 條件構(gòu)造器 QueryWrapper 的基本用法
這篇文章主要介紹了Mybatis-Plus - 條件構(gòu)造器 QueryWrapper 的使用,通過實(shí)例代碼給大家介紹了查詢示例代碼及實(shí)現(xiàn)需求,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09
Spring?Boot中常用的參數(shù)傳遞注解示例詳解
這篇文章主要介紹了Spring?Boot中常用的參數(shù)傳遞注解,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-11-11
MyBatisPlus通過ID更新數(shù)據(jù)為NULL的四種方法
本文主要介紹了MyBatisPlus通過ID更新數(shù)據(jù)為NULL的實(shí)現(xiàn)方法,包括@TableField注解、UpdateWrapper、lambdaUpdate及全局配置,具有一定的參考價(jià)值,感興趣的可以了解一下2025-08-08
SpringBoot Actuator埋點(diǎn)和監(jiān)控及簡單使用
最近做的項(xiàng)目涉及到埋點(diǎn)監(jiān)控、報(bào)表、日志分析的相關(guān)知識,于是搗鼓的一番,下面把涉及的知識點(diǎn)及SpringBoot Actuator埋點(diǎn)和監(jiān)控的簡單用法,給大家分享下,感興趣的朋友一起看看吧2021-11-11

