Mybatis--TypeHandler使用手册
TypeHandler使用手册
场景:想保存user时 teacher自动转String ,不想每次保存都要手动去转String;从DB查询出来时,也要自动帮我们转换成Java对象 Teacher
@Data
public class User {private Integer id;private String name;private Integer sex;//这里直接使用数据库无法识别的自定义类型private Teacher teacher;
}
当然Mybatis给我们提供了接口 TypeHandler
(类型映射)
public interface TypeHandler<T> {//参数转换void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;//列值转换T getResult(ResultSet rs, String columnName) throws SQLException;//列值转换T getResult(ResultSet rs, int columnIndex) throws SQLException;//列值转换T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}
看看mybatis内置的类型处理器,这就是为什么一些Java的数据类型不用我们手动转换的原因
我们可以参考String,看他是怎么处理的,发现都是通过原生的jdbc来处理的
public class StringTypeHandler extends BaseTypeHandler<String> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)throws SQLException {ps.setString(i, parameter);}@Overridepublic String getNullableResult(ResultSet rs, String columnName)throws SQLException {return rs.getString(columnName);}@Overridepublic String getNullableResult(ResultSet rs, int columnIndex)throws SQLException {return rs.getString(columnIndex);}@Overridepublic String getNullableResult(CallableStatement cs, int columnIndex)throws SQLException {return cs.getString(columnIndex);}
}
实战
我们结合springboot来看,启动容器
server:port: 8080
mybatis:mapper-locations: classpath:mappers/*.xmltype-handlers-package: com.example.ssm.demos.web.typeHandler
创建SqlSessionFactory的时候扫描并注册
public class SqlSessionFactoryBean implements InitializingBean {@Overridepublic void afterPropertiesSet() throws Exception {this.sqlSessionFactory = buildSqlSessionFactory();}protected SqlSessionFactory buildSqlSessionFactory() throws Exception {if (hasLength(this.typeHandlersPackage)) {//在包路径下找到实现TypeHandler的类并注册scanClasses(this.typeHandlersPackage, TypeHandler.class).stream().filter(clazz -> !clazz.isAnonymousClass()).filter(clazz -> !clazz.isInterface()).filter(clazz -> !Modifier.isAbstract(clazz.getModifiers())).forEach(targetConfiguration.getTypeHandlerRegistry()::register);}}
}
注册并加入缓存
public final class TypeHandlerRegistry {private final Map<Type, Map<JdbcType, TypeHandler<?>>> typeHandlerMap = new ConcurrentHashMap<>();private final Map<Class<?>, TypeHandler<?>> allTypeHandlersMap = new HashMap<>();public void register(Class<?> typeHandlerClass) {boolean mappedTypeFound = false;//如果这个类有注解@MappedTypes,根据注解的指定的类进行有参构造实例化MappedTypes mappedTypes = typeHandlerClass.getAnnotation(MappedTypes.class);if (mappedTypes != null) {for (Class<?> javaTypeClass : mappedTypes.value()) {register(javaTypeClass, typeHandlerClass);mappedTypeFound = true;}}//没有注解,直接无参构造实例化if (!mappedTypeFound) {register(getInstance(null, typeHandlerClass));}}//加入缓存 private void register(Type javaType, JdbcType jdbcType, TypeHandler<?> handler) {if (javaType != null) {Map<JdbcType, TypeHandler<?>> map = typeHandlerMap.get(javaType);if (map == null || map == NULL_TYPE_HANDLER_MAP) {map = new HashMap<>();}map.put(jdbcType, handler);typeHandlerMap.put(javaType, map);}allTypeHandlersMap.put(handler.getClass(), handler);}
}
容器启动完成,测试一下
@Mapper
public interface UserMapper {public User getUserListByEntity(Integer id);public int insertUser(User user);
}
定义一个Teacher 处理器
public class TeacherTypeHandler extends BaseTypeHandler<Teacher> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Teacher parameter, JdbcType jdbcType) throws SQLException {ps.setString(i, JSON.toJSONString(parameter));}@Overridepublic Teacher getNullableResult(ResultSet rs, String columnName) throws SQLException {return JSON.parseObject(rs.getString(columnName),Teacher.class);}@Overridepublic Teacher getNullableResult(ResultSet rs, int columnIndex) throws SQLException {return JSON.parseObject(rs.getString(columnIndex),Teacher.class);}@Overridepublic Teacher getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {return JSON.parseObject(cs.getString(columnIndex),Teacher.class);}
}
mapper文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.example.ssm.demos.web.mapper.UserMapper"><sql id="allUserCollun">id,name,sex,teacher</sql><resultMap id="userMap" type="com.example.ssm.demos.web.pojo.User"><id column="id" property="id"></id><result property="name" column="name"></result><result property="sex" column="sex"></result><!-- 指定字段处理器,反序列化成Teacher对象 --><result property="teacher" column="teacher" typeHandler="com.example.ssm.demos.web.typeHandler.TeacherTypeHandler" ></result></resultMap><!-- 测试查询 --><select id="getUserListByEntity" resultMap="userMap">select<include refid="allUserCollun"></include>from User<where>id = #{id}</where></select><!-- 测试新增 --><insert id="insertUser" parameterType="com.example.ssm.demos.web.pojo.User">insert into user(<include refid="allUserCollun"></include>) values (#{id},#{name},#{sex},<!-- 指定字段处理器,转换成json格式的字符串 -->#{teacher,typeHandler=com.example.ssm.demos.web.typeHandler.TeacherTypeHandler})</insert>
</mapper>
经过测试,完全没有问题,插入数据库时,自动转 String
,查询时,自动转 Teacher
如果想知道调用位置,参数可以看这个类: org.apache.ibatis.scripting.defaults.DefaultParameterHandler#setParameters
返回值可以看这个类: org.apache.ibatis.executor.resultset.DefaultResultSetHandler#getPropertyMappingValue
相关文章:
Mybatis--TypeHandler使用手册
TypeHandler使用手册 场景:想保存user时 teacher自动转String ,不想每次保存都要手动去转String;从DB查询出来时,也要自动帮我们转换成Java对象 Teacher Data public class User {private Integer id;private String name;priva…...
网络编程(TCP、UDP)
文章目录 一、概念1.1 什么是网络编程1.2 网络编程中的基本知识 二、Socket套接字2.1 概念及分类2.2 TCP VS UDP2.3 通信模型2.4 接口方法UDP数据报套接字编程TCP流套接字编程 三、代码示例3.1 注意点3.2 回显服务器基于UDP基于TCP 一、概念 首先介绍了什么是网络编程ÿ…...
Python快速入门系列-7(Python Web开发与框架介绍)
第七章:Python Web开发与框架介绍 7.1 Flask与Django简介7.1.1 Flask框架Flask的特点Flask的安装一个简单的Flask应用示例7.1.2 Django框架Django的特点Django的安装一个简单的Django应用示例7.2 前后端交互与数据传输7.2.1 前后端交互7.2.2 数据传输格式7.2.3 示例:使用Flas…...
最长对称子串
对给定的字符串,本题要求你输出最长对称子串的长度。例如,给定Is PAT&TAP symmetric?,最长对称子串为s PAT&TAP s,于是你应该输出11。 输入格式: 输入在一行中给出长度不超过1000的非空字符串。 输出格式&…...
【大模型】大模型 CPU 推理之 llama.cpp
【大模型】大模型 CPU 推理之 llama.cpp llama.cpp安装llama.cppMemory/Disk RequirementsQuantization测试推理下载模型测试 参考 llama.cpp 描述 The main goal of llama.cpp is to enable LLM inference with minimal setup and state-of-the-art performance on a wide var…...
异地组网怎么管理?
在当今信息化时代,随着企业的业务扩张和员工的分布,异地组网已经成为越来越多企业的需求。异地组网管理相对来说是一项复杂而繁琐的任务。本文将介绍一种名为【天联】的管理解决方案,帮助企业更好地管理异地组网。 【天联】组网的优势 【天联…...
Kafka参数介绍
官网参数介绍:Apache KafkaApache Kafka: A Distributed Streaming Platform.https://kafka.apache.org/documentation/#configuration...
如何利用待办事项清单提高工作效率?
你是否经常因为繁重的工作量而感到不堪重负?你是否在努力赶工期或经常忘记重要的电子邮件?你并不是特例。如何利用待办事项清单提高工作效率?这里有一个简单的方法可以帮你理清混乱并更高效地完成任务—待办事项清单。 这种类型的清单可以帮…...
力扣经典150题第二题:移除元素
移除元素问题详解与解决方法 1. 介绍 移除元素问题是 LeetCode 经典题目之一,要求原地修改输入数组,移除所有数值等于给定值的元素,并返回新数组的长度。 问题描述 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等…...
55555555555555
欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和…...
用Skimage学习数字图像处理(018):图像形态学处理(上)
本节开始讨论图像形态学处理,这是上篇,将介绍与二值形态学相关的内容,重点介绍两种基本的二值形态学操作:腐蚀和膨胀,以及三种复合二值形态学操作:开、闭和击中击不中变换。 目录 9.1 基础 9.2 基本操作…...
MySQL中 in 和 exists 区别
在MySQL中,IN和EXISTS都是用于在子查询中测试条件的操作符,但它们在处理和效率上有一些重要的区别。MySQL中的in语句是把外表和内表作hash连接,⽽exists语句是对外表作loop循环,每次loop循环再对内表进⾏查询。⼤家⼀直认为exists…...
Java基础 - 代码练习
第一题:集合的运用(幸存者) public class demo1 {public static void main(String[] args) {ArrayList<Integer> array new ArrayList<>(); //一百个囚犯存放在array集合中Random r new Random();for (int i 0; i < 100; …...
【Redis】redis集群模式
概述 Redis集群,即Redis Cluster,是Redis 3.0开始引入的分布式存储方案。实际使用中集群一般由多个节点(Node)组成,Redis的数据分布在这些节点中。集群中的节点分为主节点和从节点:只有主节点负责读写请求和集群信息的维护&#…...
基于opencv的猫脸识别模型
opencv介绍 OpenCV的全称是Open Source Computer Vision Library,是一个跨平台的计算机视觉库。OpenCV是由英特尔公司发起并参与开发,以BSD许可证授权发行,可以在商业和研究领域中免费使用。OpenCV可用于开发实时的图像处理、计算机视觉以及…...
基于注意力整合的超声图像分割信息在乳腺肿瘤分类中的应用
基于注意力整合的超声图像分割信息在乳腺肿瘤分类中的应用 摘要引言方法 Segmentation information with attention integration for classification of breast tumor in ultrasound image 摘要 乳腺癌是世界范围内女性最常见的癌症之一。基于超声成像的计算机辅助诊断&#x…...
数据库重点知识(个人整理笔记)
目录 1. 索引是什么? 1.1. 索引的基本原理 2. 索引有哪些优缺点? 3. MySQL有哪几种索引类型? 4. mysql聚簇和非聚簇索引的区别 5. 非聚簇索引一定会回表查询吗? 6. 讲一讲前缀索引? 7. 为什么索引结构默认使用B…...
[技术闲聊]checklist
电路设计完成后,需要确认功能完整性,明确是否符合设计规格需求;需要确认电路设计是否功能符合但是系列项不符合设计规则,如果都没有问题,那么就可以发给layout工程师。 今天主要讲讲电路设计规则,涉及到一…...
力扣刷题 二叉树的迭代遍历
题干 给你二叉树的根节点 root ,返回它节点值的 前序 遍历。 示例 1: 输入:root [1,null,2,3] 输出:[1,2,3]示例 2: 输入:root [] 输出:[]示例 3: 输入:root [1] 输…...
【二】Django小白三板斧
今日内容 静态文件配置 request对象方法初识 pycharm链接数据库(MySQL) django链接数据库(MySQL) Django ORM简介 利用ORM实现数据的增删查改 【一】Django小白三板斧 HttpResponse 返回字符串类型的数据 render 返回HTML文…...
MyBatis的基本应用
源码地址 01.MyBatis环境搭建 添加MyBatis的坐标 <!--mybatis坐标--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.9</version></dependency><!--mysql驱动坐…...
Day80:服务攻防-中间件安全HW2023-WPS分析WeblogicJettyJenkinsCVE
目录 中间件-Jetty-CVE&信息泄漏 CVE-2021-34429(信息泄露) CVE-2021-28169(信息泄露) 中间件-Jenkins-CVE&RCE执行 cve_2017_1000353 CVE-2018-1000861 cve_2019_1003000 中间件-Weblogic-CVE&反序列化&RCE 应用金山WPS-HW2023-RCE&复现&上线…...
使用generator实现async函数
我们先来看一下async函数是怎么使用的 const getData (sec) > new Promise((resolve) > {setTimeout(() > resolve(sec * 2), sec * 1000);})// aim to get this asycnFun by generator async function asyncFun() {const data1 await getData(1);const data2 awa…...
go并发请求url
sync.WaitGroup写法 package mainimport ("database/sql""fmt""net/http""sync""time"_ "github.com/go-sql-driver/mysql" )func main() {//开始计时start : time.Now()//链接数据库,用户名…...
刷题之Leetcode704题(超级详细)
704. 二分查找 力扣题目链接(opens new window)https://leetcode.cn/problems/binary-search/ 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标&am…...
leetcode热题100.前k个高频元素
作者:晓宜 🌈🌈🌈 个人简介:互联网大厂Java准入职,阿里云专家博主,csdn后端优质创作者,算法爱好者 ❤️❤️❤️ 你的关注是我前进的动力😊 Problem: 347. 前 K 个高频元…...
LangChain Demo | Agent X ReAct X wikipedia 询问《三体》的主要内容
背景 LangChain学习中,尝试改了一下哈里森和吴恩达课程当中的问题,看看gpt-3.5-turbo在集成了ReAct和wikipedia后,如何回答《三体》的主要内容是什么这个问题,当然,主要是为了回答这问题时LangChain内部发生了什么。所…...
Revit 2025新功能一览~
Hello大家好!我是九哥~ Revit2025已经更新,安装后,简单试了下,还是挺不错的,流畅度啊,新功能啊,看来还是有听取用户意见的,接下来就简单看看都有哪些新功能。 好了,今天的…...
Head First Design Patterns -代理模式
什么是代理模式 代理模式为另一个对象提供替身或者占位符,以便控制客户对对象的访问,管理访问的方式有很多种。例如远程代理、虚拟代理、保护代理等。 远程代理:管理客户和远程对象之间的交互。 虚拟代理:控制访问实例化开销大的对…...
第十三题:天干地支
题目描述 古代中国使用天干地支来记录当前的年份。 天干一共有十个,分别为:甲(jiǎ)、乙(yǐ)、丙(bǐng)、丁(dīng)、戊(w)、己&a…...
上海建设安全生产协会网站/百度账号安全中心官网
公众号关注 「奇妙的 Linux 世界」设为「星标」,每天带你玩转 Linux !11月28日,硅谷时间凌晨3点,Twitter的软件工程师们收到了一封来自公司的电子邮件,告诉他们当晚将进行新一轮的代码审查,他们必须准备好展…...
网站加视频播放设计怎么做的/seo百度关键词优化
1、首先去(http://www.apachelounge.com/download/)下载一个合适的mod_fcgid 文件。 2、将解压后的文件改为mod_fcgid.dll 并复制到apache的module目录下面。3、打开httpd.conf文件,添加如下内容:1 LoadModule fcgid_module modules/mod_fcgid.so 2 &l…...
日照网站建设官方网站/百度人工
1.首先确定要计算时间的时区,jdk8支持,根据时区ID来判断是否处于夏令时。 2.根据要判断时区的id和对应的时间,即可判断出是否处于夏令时。 public static boolean currentTimeIsDaylightTime(long time) { Calendar calendar Calendar.ge…...
自己如何做独立网站/免费推广app软件下载
不经过Postmaster以单用户模式直接启动,为单一用户提供服务,这种方式由–single选项启动。在这种模式下,Postgres服务器进程必须自己完成初始化内存环境、配置参数等操作。 /* Initialize startup process environment if necessary. */if (!…...
wordpress视屏教程/阿里云搜索
本文讲的是在Docker上运行.NET Core,【编者的话】本文为Jurgis Pasukonis在medium.com博客中发布的关于在Docker上运行.NET Core的文章,介绍了目前.NET Core在Docker上的开源情况及部分演示。Jurgis目前是TRAFI公司的CTO。 对于Microsoft和.NET来说&…...
静态营销网站代码/重庆网站搜索排名
解法一:http://siukwan.sinaapp.com/?p189 https://www.cnblogs.com/TonyYPZhang/p/5123058.html 1.这道题目主要是求一个无向图中,以哪个节点为根节点的树的高度最小; 2.常规方法可以使用BFS或者DFS,对每个点都遍历一遍&…...