Mybatis自定义类型映射处理器
目录
- 前言
- 运行环境
- 创建表
- 导入依赖
- 创建实体
- 建立TypeHandler
- @MappedJdbcTypes和@MappedTypes干什么用的
- BaseTypeHandler要实现的方法是干什么的
- 写好的TypeHandler怎么使用
- 创建dao
- 控制层
前言
mybatis作为一款相当优秀的一款orm框架,不仅本身就提供了很多类型映射,还支持自定义类型映射(javaType与jdbcType之间的关系),通过TypeHandler我们可以自己在数据库类型与实体类型之间任意转换。
比如说,我现在需要讲前端传来的手机号进行脱敏入库处理,而用户查的时候,看到的得是正常的!这就涉及加密解密处理了,当然我们可以在service里处理,这里我们演示下如何通过自定义类型映射,进行处理。
运行环境
java8, springboot2.5.0,mysql8,maven3.3.9
创建表
CREATE TABLE `t_user` (`id` int(10) NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,`phone` varchar(255) DEFAULT NULL,`remark` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
导入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.4</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.6.5</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency>
创建实体
import java.util.List;public class User {private Integer id;private String name;private MyEncrypt phone;private List<String> remark;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public MyEncrypt getPhone() {return phone;}public void setPhone(MyEncrypt phone) {this.phone = phone;}public String getName() {return name;}public void setName(String name) {this.name = name;}public List<String> getRemark() {return remark;}public void setRemark(List<String> remark) {this.remark = remark;}
}
public class MyEncrypt {private String realPhone;public MyEncrypt(String realPhone) {this.realPhone = realPhone;}public String getRealPhone() {return realPhone;}public void setRealPhone(String realPhone) {this.realPhone = realPhone;}
}
数据库手机号设置的varchar类型,而我定义的是一个MyEncrypt
实体类,所以我需要将他与jdbcType关联起来,并且完成加密解密的过程!
建立TypeHandler
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import com.jcl.mybatistypehandler.model.MyEncrypt;
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.nio.charset.StandardCharsets;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(MyEncrypt.class)
public class MyEncryptTypeHandler extends BaseTypeHandler<MyEncrypt> {private static final byte[] KEYS = "12345678abcdefgh".getBytes(StandardCharsets.UTF_8);/*** 设置参数,默认从前端传来是源手机号,加密处理后,又重新塞回* preparedStatement: 预执行句柄*/@Overridepublic void setNonNullParameter(PreparedStatement preparedStatement, int i, MyEncrypt myEncrypt, JdbcType jdbcType) throws SQLException {if (myEncrypt == null || myEncrypt.getRealPhone() == null) {preparedStatement.setString(i, null);return;}String phone = myEncrypt.getRealPhone();AES aes = SecureUtil.aes(KEYS);String encrypt = aes.encryptHex(phone);preparedStatement.setString(i, encrypt);}@Overridepublic MyEncrypt getNullableResult(ResultSet resultSet, String s) throws SQLException {return decrypt(resultSet.getString(s));}@Overridepublic MyEncrypt getNullableResult(ResultSet resultSet, int i) throws SQLException {return decrypt(resultSet.getString(i));}@Overridepublic MyEncrypt getNullableResult(CallableStatement callableStatement, int i) throws SQLException {return decrypt(callableStatement.getString(i));}/*** 解密** @param value 手机号* @return 返回解密对象*/public MyEncrypt decrypt(String value) {if (null == value) {return null;}return new MyEncrypt(SecureUtil.aes(KEYS).decryptStr(value));}
}
以上就是全文核心,看的就是这里!
@MappedJdbcTypes和@MappedTypes干什么用的
我认为表面上是对jdbcType和javaType做了个绑定,更像是做了个筛选。比如我上面
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(MyEncrypt.class)
就是将MyEncrypt
和varchar
建立了联系,你的参数里有MyEncrypt这个类型且是要转成varchar的,他才会起作用!
BaseTypeHandler要实现的方法是干什么的
他要实现一个set方法和三个get方法。
setNonNullParameter
是塞值,我理解成把javaType转成jdbcType的过程(通俗点是把让你把传的对象转成你能放进数据库类型)
getNullableResult
被重载了两次,但是在我眼里他就是和上面反过来,是把jdbcType转成javaType的过程,也就是把数据库里的数据转成你约定的对象。
写好的TypeHandler怎么使用
个人建议全局配在配置文件里,写在xml里,不仅麻烦,还报各种错误,麻烦死了。而且一般写这个,大概率是为了全局使用的!
# 包名
mybatis.type-handlers-package=com.jcl.mybatistypehandler.handler
写在xml里的话,那可就麻烦了
高度建议全局配
<?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.jcl.mybatistypehandler.dao.UserDao"><resultMap id="BaseResultMapper" type="com.jcl.mybatistypehandler.model.User"><id column="id" property="id"/><result column="name" property="name"/><result column="phone" property="phone" typeHandler="com.jcl.mybatistypehandler.handler.MyEncryptTypeHandler"/><result column="remark" property="remark" typeHandler="com.jcl.mybatistypehandler.handler.ListTypeHandler"/></resultMap><insert id="add">insert into t_user(name, phone, remark)values (#{name}, #{phone,typeHandler=com.jcl.mybatistypehandler.handler.MyEncryptTypeHandler},#{remark,typeHandler=com.jcl.mybatistypehandler.handler.ListTypeHandler})</insert><select id="findByPhone" resultMap="BaseResultMapper">select *from t_userwhere phone = #{phone,typeHandler=com.jcl.mybatistypehandler.handler.MyEncryptTypeHandler}</select>
</mapper>
创建dao
import com.jcl.mybatistypehandler.model.MyEncrypt;
import com.jcl.mybatistypehandler.model.User;
import org.apache.ibatis.annotations.Param;public interface UserDao {int add(@Param("name") String name,@Param("phone") MyEncrypt phone, @Param("remark") String remark);User findByPhone(@Param("phone") MyEncrypt phone);
}
xml上面已给!
ListTypeHandler是我设定的一个字符串转List的一个转换器!
可以不写,所以xml里面也就别配了!
package com.jcl.mybatistypehandler.handler;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 org.springframework.util.StringUtils;import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(List.class)
public class ListTypeHandler extends BaseTypeHandler<List<String>> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType) throws SQLException {if (null == parameter || parameter.isEmpty()) {ps.setString(i, null);return;}ps.setString(i, String.join(",", parameter));}@Overridepublic List<String> getNullableResult(ResultSet rs, String columnName) throws SQLException {final String value = rs.getString(columnName);if (StringUtils.hasText(value)) {return Arrays.asList(value.split(","));}return null;}@Overridepublic List<String> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {final String value = rs.getString(columnIndex);if (StringUtils.hasText(value)) {return Arrays.asList(value.split(","));}return null;}@Overridepublic List<String> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {final String value = cs.getString(columnIndex);if (StringUtils.hasText(value)) {return Arrays.asList(value.split(","));}return null;}
}
控制层
import com.jcl.mybatistypehandler.dao.UserDao;
import com.jcl.mybatistypehandler.model.MyEncrypt;
import com.jcl.mybatistypehandler.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class UserController {@Autowiredprivate UserDao userDao;@GetMapping("add")public String addUser(@RequestParam("name") String name,@RequestParam("phone") String phone,@RequestParam("remark") String remark) {MyEncrypt myEncrypt = new MyEncrypt(phone);int result = userDao.add(name, myEncrypt, remark);return "添加结果: " + result;}@GetMapping("findByPhone")public User findCustomer(@RequestParam("phone") String phone) {return userDao.findByPhone(new MyEncrypt(phone));}
}
Mybatis自定义类型映射处理器相关推荐
- MyBatis自定义类型处理器(typeHandler)
MyBatis自定义类型处理器(typeHandler) 我们执行sql语句通过PreparedStatement语句实现,PreparedStatement会设置?值,类型处理器帮PreparedS ...
- mybatis date类型映射_Mybatis中类型映射处理器详解
上一篇梳理了Configuration初始化分析,今天继续typeHandlers部分. 数据库厂商标识 接上一篇文章分析,下一个解析的是databaseIdProvider节点,这个节点好理解,从字 ...
- MyBatis自定义类型处理器 TypeHandler
在项目开发中经常会遇到一个问题: 当我们在javabean中自定义了枚举类型或者其它某个类型,但是在数据库中存储时往往需要转换成数据库对应的类型,并且在从数据库中取出来时也需要将数据库类型转换为jav ...
- mybatis date类型映射_MapStruct 映射工具
MapStruct 映射工具 本篇主要讲解MapStruct 一款映射工具,只需简单的定义一个Mapper接口,在编译期间,MapStruct将生成此接口的实现,据说MapStruct性能最高是Spr ...
- jpa配置映射包_JPA – Hibernate –包级别的类型映射
jpa配置映射包 当我们最终成熟到可以在JPA中使用某些自定义类型映射时,我们通常会停留在某些提供程序特定的解决方案上,因为JPA本身并未定义任何用于执行此操作的机制. 让我为您展示一个JPA提供程序 ...
- JPA – Hibernate –包级别的类型映射
当我们最终成熟到可以在JPA中使用某些自定义类型映射时,我们通常会停留在某些提供程序特定的解决方案上,因为JPA本身并未定义任何实现此功能的机制. 让我为您展示一个JPA提供程序Hibernate的自 ...
- FreeSql (三十三)CodeFirst 类型映射
前面有介绍过几篇 CodeFirst 内容文章,有 <(二)自动迁移实体>(https://www.cnblogs.com/FreeSql/p/11531301.html) <(三) ...
- java高级用法之:在JNA中使用类型映射
文章目录 简介 类型映射的本质 TypeMapper NativeMapped 总结 简介 JNA中有很多种映射,library的映射,函数的映射还有函数参数和返回值的映射,libary和函数的映射比 ...
- MyBatis核心源码剖析(SqlSession XML解析 Mapper executor SQL执行过程 自定义类型处理器 缓存 日志)
MyBatis核心源码剖析 MyBatis核心源码剖析 1 MyBatis源码概述 1.1 为什么要看MyBatis框架的源码 1.2 如何深入学习MyBatis源码 1.3 源码分析的5大原则 2 ...
最新文章
- ESP8266 WiFi探针 MAC
- error connection reset by peer 104
- Qt文档阅读笔记-Qt Core的官方解析
- html页面怎么解决跨域问题,前端web开发html如何避免js的跨域访问
- 三年级开始学计算机,三年级学生初识计算机的教学心得
- 计算机网络基础笔记 运输层协议UDP/TCP
- WordPress博客添加首页、文章页、页面、分类页、标签页的关键字和描述
- Java代码编写规范总结
- 服务器共享文件防复制软件,大势至禁止复制服务器共享文件软件
- 计算机表格折线图添加图例,如何将Excel表格中插入的折线图中的圆圈设置为方块或三角形...
- 如何生成3分钟,5分钟,n分钟K线数据
- 计算机校本培训 培训总结,校本培训工作总结(2015—2016学年度)
- VMware Workstation16设置共享文件夹
- mac笔记本电脑外接显示器没有声音
- 系统架构中常见问题及解决方案
- 你要找到黑夜里代替阳光的东西,那个叫做信念
- Python数据分析6——数据规整
- C++ vector数组实现多级排序—使用sort()函数
- 华为交换机 查ip冲突_巧用交换机控制IP地址冲突故障的技巧
- 原装应广单片机 MCU芯片PMS152 SOP8封装 单片机开发