Mybatis枚举类型处理和类型处理器
专栏精选
引入Mybatis
Mybatis的快速入门
Mybatis的增删改查扩展功能说明
mapper映射的参数和结果
Mybatis复杂类型的结果映射
Mybatis基于注解的结果映射
Mybatis枚举类型处理和类型处理器
再谈动态SQL
Mybatis配置入门
Mybatis行为配置之Ⅰ—缓存
Mybatis行为配置之Ⅱ—结果相关配置项说明
Mybatis行为配置之Ⅲ—其他行为配置项说明
Mybatis行为配置之Ⅳ—日志
Mybatis整合Spring详解
Mybatis插件入门
Mybatis专栏代码资源
文章目录
- 专栏精选
- 摘要
- 引言
- 正文
- 枚举类型映射
- 简单枚举映射
- 枚举顺序映射
- 复杂枚举映射
- 类型处理器
- 总结
摘要
在这篇文章中,我们将进入Mybatis类型转换器的世界,了解Mybatis中如何使用枚举类型和Mybatis类型转换器的基本用法,其中的很多观点或内容都能在一定程度上让我们的开发之旅更加轻松方便,这是一个菜鸟提升技术能力,老鸟巩固基础知识的好机会。准备好开启今天的神奇之旅了吗?
引言
大家好,我是奇迹老李,一个专注于分享开发经验和基础教程的博主。这里是我的其中一个技术分享平台,欢迎广大朋友们点赞评论提出意见,重要的是点击关注喔 🙆。今天要和大家分享的内容是枚举类型处理和类型处理器。做好准备,Let’s go🚎🚀
正文

枚举类型映射
简单枚举映射
如果需要返回枚举类型的查询结果,如果返回值和枚举值一一对应,可以直接使用枚举类型接收返回结果。
新增字典数据
INSERT INTO dict_test (dict_name, dict_code, dict_type, dict_sort) VALUES ('NONE', '1', 'app_auth_type', 0);
INSERT INTO dict_test (dict_name, dict_code, dict_type, dict_sort) VALUES ('MOBILE', '2', 'app_auth_type', 2);
INSERT INTO dict_test (dict_name, dict_code, dict_type, dict_sort) VALUES ('WECHAT', '3', 'app_auth_type', 3);
INSERT INTO dict_test (dict_name, dict_code, dict_type, dict_sort) VALUES ('QQ', '4', 'app_auth_type', 4);
新增枚举类
public enum AuthType { NONE,WECHAT,QQ,MOBILE;
}
mapper映射
AuthType getAuthType(@Param("code")String code);
<select id="getAuthType" resultType="top.sunyog.common.entity.AuthType"> select dict_name from dict_test where dict_type='app_auth_type' and dict_code=#{code}
</select>
测试类
private void testEnumResultService(SimpleQueryMapper mapper){ AuthType authType = mapper.getAuthType("3"); System.out.println(authType);
}
打印结果
WECHAT
枚举顺序映射
mybatis内置了EnumOrdinalTypeHandler类型处理器,来实现字典顺序号和枚举类型之间的映射。注意枚举类型的顺序号从0开始。
代码示例:
mapper-xml
<resultMap id="app-auth-order" type="map"> <result property="auth_type" column="auth_type" javaType="top.sunyog.common.entity.AuthType" typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/>
</resultMap>
<select id="getAppAuthOrder" resultMap="app-auth-order"> select auth_type from app_test where id=#{id}
</select>
mapper接口
Map<String,Object> getAppAuthOrder(@Param("id") Long id);
测试类:
public class SimpleQueryService extends MybatisService<SimpleQueryMapper>{private void testEnumOrdder(SimpleQueryMapper mapper) { Map<String, Object> map = mapper.getAppAuthOrder(2L); map.entrySet().forEach(o-> System.out.println(o.getKey()+": "+o.getValue())); }
}
打印结果(auth_type=2)
auth_type: QQ
复杂枚举映射
对于返回值和枚举名称不对应的情况,可以使用自定义类型处理器的方式解决,
在类型处理器中处理数据库数据和枚举类型之间的对应关系
自定义类型处理器
public class AppAuthTypeHandler extends BaseTypeHandler<AppStatus> { @Override public void setNonNullParameter(PreparedStatement ps, int i, AppStatus parameter, JdbcType jdbcType) throws SQLException { ps.setString(i,this.appStatusToString(parameter)); } @Override public AppStatus getNullableResult(ResultSet rs, String columnName) throws SQLException { String str = rs.getString(columnName); return this.stringToAppStatus(str); } @Override public AppStatus getNullableResult(ResultSet rs, int columnIndex) throws SQLException { String str = rs.getString(columnIndex); return this.stringToAppStatus(str); } @Override public AppStatus getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { String str = cs.getString(columnIndex); return this.stringToAppStatus(str); } private String appStatusToString(AppStatus status){ switch (status){ case FREEZE: return "冻结应用"; case NORMAL: return "正常应用"; case OVERDUE: return "过期应用"; case TEMPORARY: default: return "临时应用"; } } private AppStatus stringToAppStatus(String str){ switch (str){ case "冻结应用": return AppStatus.FREEZE; case "正常应用": return AppStatus.NORMAL; case "过期应用": return AppStatus.OVERDUE; default: return AppStatus.TEMPORARY; } }
}
定义新的结果值类型
public class AppDict { private AppStatus appStatus; public AppStatus getAppStatus() { return appStatus; } public void setAppStatus(AppStatus appStatus) { this.appStatus = appStatus; } @Override public String toString() { return "AppDict{" + "appStatus=" + appStatus + '}'; }
}
新增mapper方法
AppDict getAppStatusEnum(@Param("code")String code);
定义映射文件,通过resultMap设置类型处理器
<resultMap id="app-status-enum" type="top.sunyog.common.entity.AppDict"> <result property="appStatus" column="dict_name" typeHandler="top.sunyog.mybatis.handler.AppAuthTypeHandler"/>
</resultMap>
<select id="getAppStatusEnum" resultMap="app-status-enum"> select dict_name from dict_test where dict_type='app_status' and dict_code=#{code}
</select>
测试代码
private void testEnumStatusService(SimpleQueryMapper mapper){ AppDict appDict = mapper.getAppStatusEnum("1"); System.out.println(appDict);
}
打印结果
AppDict{appStatus=FREEZE}
类型处理器
以上对复杂枚举映射的解决方式即是类型处理器的简单应用,在开发过程中更常见的是对LocalDateTime等事件类型的转换。
这是因为在Mybatis的早期版本中,对于日期类型的数据通常使用
Java.util.Date类型接收,如果使用java.time.LocalDateTime类型接收该字段会造成结果值为空的情况,这时候要么升级Mybatis版本,要么通过自定义类型处理器实现
降低mybatis版本到3.4.4
<dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.4</version> </dependency>
</dependencies>
此时重新启动项目会报错,需要修改启动类
public class MybatisAppContext { private static SqlSessionFactory sqlSessionFactory = null; private Map<String, MybatisService> serviceMap = new ConcurrentHashMap<>(); /** * 注册SqlSessionFactory */ static { SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); try (InputStream in = MybatisApp.class.getResourceAsStream("/mybatis-config.xml"); InputStreamReader reader=new InputStreamReader(in)) { sqlSessionFactory = builder.build(reader); } catch (IOException e) { System.out.println("文件路径读取错误"); } }...
}
此时再启动项目仍会报错,提示没有对应的类处理器
新增类型处理器 LocalDateHandler
package top.sunyog.mybatis.handler; 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;
import java.time.LocalDate; public class LocalDateHandler extends BaseTypeHandler<LocalDate> { @Override public void setNonNullParameter(PreparedStatement ps, int i, LocalDate parameter, JdbcType jdbcType) throws SQLException { ps.setObject(i,parameter); } @Override public LocalDate getNullableResult(ResultSet rs, String columnName) throws SQLException { return rs.getObject(columnName,LocalDate.class); } @Override public LocalDate getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return rs.getObject(columnIndex,LocalDate.class); } @Override public LocalDate getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return cs.getObject(columnIndex,LocalDate.class); }
}
配置文件添加配置项typeHandler
<settings .../>
<typeAliasis .../><typeHandlers> <typeHandler handler="top.sunyog.mybatis.handler.LocalDateHandler"/>
</typeHandlers><environments .../><mappers .../>
测试代码
public class SimpleQueryService extends MybatisService<SimpleQueryMapper>{ @Override public void doService() { SimpleQueryMapper mapper = super.getMapper(SimpleQueryMapper.class); this.testHashMapParam(mapper);}
}
打印结果
AppTestEntity{id=5, appName='名称1', appCode='code-1', authType='2', createDate=2023-11-03, creator='admin3', appStatus='null', authTypeDict=null, appStatusDict=null, services=null}
AppTestEntity{id=6, appName='name2', appCode='code-2', authType='2', createDate=2023-11-03, creator='admin3', appStatus='null', authTypeDict=null, appStatusDict=null, services=null}
AppTestEntity{id=7, appName='jack liu', appCode='code-3', authType='2', createDate=2023-11-03, creator='admin3', appStatus='null', authTypeDict=null, appStatusDict=null, services=null}
注意:以上处理方式只能解决由于Mybatis版本原因造成的LocalDateTime或LocalDate等的类型转换失败问题。但类型转换失败有可能是数据库驱动、或连接池的版本问题造成的,实际开发过程中遇到过在Oracle数据库中ojdbc7驱动接收LocalDateTime类时间数据失败报错的问题,一般通过升级到ojdbc8都能解决。如果项目版本升级比较麻烦,可以使用Date类型接收日期时间数据,在service层再做转换或不转换,通过@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone="GMT+8")注解的方式指定时区保证时间的准确性
总结
本文我们介绍了在Mybatis中如何使用枚举类型接收查询结果,并以此引入Mybatis 的类型处理器。通过日期类型处理器类认识了类型处理器的简单使用,在业务开发过程中,可以通过设计功能更强大的类型处理器来更优雅的实现各种相关业务需求。
我们在Mybatis的增删改查扩展功能说明这篇文章最后提到的疑问4和疑问5也得到了解决。
📩 联系方式
邮箱:qijilaoli@foxmail.com❗版权声明
本文为原创文章,版权归作者所有。未经许可,禁止转载。更多内容请访问奇迹老李的博客首页
相关文章:
Mybatis枚举类型处理和类型处理器
专栏精选 引入Mybatis Mybatis的快速入门 Mybatis的增删改查扩展功能说明 mapper映射的参数和结果 Mybatis复杂类型的结果映射 Mybatis基于注解的结果映射 Mybatis枚举类型处理和类型处理器 再谈动态SQL Mybatis配置入门 Mybatis行为配置之Ⅰ—缓存 Mybatis行为配置…...
2023 NCTF writeup
CRYPTO Sign 直接给了fx,gx,等于私钥给了,直接套代码,具体可以参考: https://0xffff.one/d/1424 fx [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…...
golang的大杀器协程goroutine
在Golang中,协程(Goroutine)是轻量级的执行单元,用于实现并发编程。它是Golang语言的重要组成部分,提供了简洁、高效的方式来处理并发任务。 特点: 1)轻量级:Go语言的协程是轻量级…...
[Angular] 笔记 9:list/detail 页面以及@Output
1. Output input 好比重力,向下传递数据,list 传给 detail,smart 组件传给 dumb 组件,父组件传给子组件。input 顾名思义,输入数据给组件。 output 与之相反,好比火箭,向上传递数据或事件。ou…...
Linux学习笔记(一)
如果有自己的物理服务器请先查看这篇文章 文章目录 网卡配置Linux基础指令ls:列出目录内容cd(mkdir.rmkdir): 切换文件夹(创建,删除操作)cp:复制文件或目录mv:文件/文件夹移动cat:查看文件vi:文件查看编辑man:查看命令手册more: 查看文件内容less : 查看文件内容 ps: 显示当前进…...
Python 爬虫 教程
python爬虫框架:Scrapyd,Feapder,Gerapy 参考文章: python爬虫工程师,如何从零开始部署ScrapydFeapderGerapy? - 知乎 神器!五分钟完成大型爬虫项目 - 知乎 爬虫框架-feapder - 知乎 scrap…...
uniapp原生插件 - android原生插件打包流程 ( 避坑指南一)
【彩带- 避坑知识点】: 当时开发中安卓插件打包成功后,uniapp引用插件aar,用云打包 ,总是提示不包含插件。原因是因为module的androidManifest.xml文件没有注册activity。 这一步 很重要,一定要注册。 --------------------------…...
搭建maven私服
maven maven简介 什么是maven? Maven这个单词来自于意第绪语(犹太语),意为知识的积累。 Maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的项目管理工具软件。 Maven 除了以…...
EST-100身份证社保卡签批屏按捺终端PC版web版本http协议接口文档,支持web网页开发对接使用
<!DOCTYPE html><html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width,initial-scale1.0"><title>演示DEMO</title><script type"text/…...
基于SpringBoot的毕业论文管理系统
文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于SpringBoot的毕业论文管理系统,java…...
iToF人脸识别
iToF(间接飞行时间)是一种测量光飞行时间的技术,主要应用于人脸识别。 iToF人脸识别技术在哪些场景下会用到 iToF人脸识别技术可以应用于许多场景,以下是一些常见的应用场景: 平安城市:在城市监控系统中,iToF人脸识别技术可以用于实时监控、目标检测和识别,以及异常行为…...
Django开发3
Django开发3 Django开发编辑用户9.靓号管理9.1 表结构9.2 靓号列表9.3 新建靓号9.4 编辑靓号9.5 搜索手机号9.6 分页 10.时间插件11.ModelForm和BootStrap操作 各位小伙伴想要博客相关资料的话关注公众号:chuanyeTry即可领取相关资料! Django开发 部门管…...
MS2358:96KHz、24bit 音频 ADC
产品简述 MS2358 是带有采样速率 8kHz-96kHz 的立体声音频模数 转换器,适合于面向消费者的专业音频系统。 MS2358 通过使用增强型双位 Δ - ∑ 技术来实现其高精度 的特点。 MS2358 支持单端的模拟输入,所以不需要外部器 件,非常适…...
【Android12】Android Framework系列---tombstone墓碑生成机制
tombstone墓碑生成机制 Android中程序在运行时会遇到各种各样的问题,相应的就会产生各种异常信号,比如常见的异常信号 Singal 11:Segmentation fault表示无效的地址进行了操作,比如内存越界、空指针调用等。 Android中在进程(主要…...
中间件系列 - Redis入门到实战(原理篇)
前言 学习视频: 黑马程序员Redis入门到实战教程,深度透析redis底层原理redis分布式锁企业解决方案黑马点评实战项目 中间件系列 - Redis入门到实战 本内容仅用于个人学习笔记,如有侵扰,联系删除 学习目标 Redis数据结构Redis网…...
P2249 【深基13.例1】查找
P2249 【深基13.例1】查找 P2249 【深基13.例1】查找 题意 输入n 个不超过10的9次方的单调不减的(就是后面的数字不小于前面的数字)非负整数a1,a2,a3…然后进行 m 次询问。对于每次询问,给出一个整数q,要…...
linux常用shell脚本
查看系统当前进程连接数 netstat -an | grep ESTABLISHED | wc -l 如何在/usr目录下找出大小超过10MB的文件? find /usr -type f -size 10240k 添加一条到192.168.3.0/24的路由,网关为192.168.1.254? route add -net 192.168.3.0/24 netmask 255.2…...
Rust学习笔记005:结构体 struct
在 Rust 中,struct 是一种用于创建自定义数据类型的关键字,它允许你定义和组织数据的结构。struct 可以包含多个不同类型的字段(fields),每个字段都有一个名称和一个类型。 定义结构体 下面是一个简单的例子ÿ…...
maven中dependencyManagement标签
简介 dependencyManagement正如其名,用于项目依赖的统一管理。 在父项目中的pom.xml文件中加入dependencyManagement标签即可完成依赖版本的声明。在声明完成后,子项目(module)中引用相同的依赖时可以不指定version标签自动引入…...
SparkStreaming与Kafka整合
1.3 SparkStreaming与Kafka整合 1.3.1 整合简述 kafka是做消息的缓存,数据和业务隔离操作的消息队列,而sparkstreaming是一款准实时流式计算框架,所以二者的整合,是大势所趋。 二者的整合,有主要的两大版本。 kaf…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...
代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...
AI语音助手的Python实现
引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...
PydanticAI快速入门示例
参考链接:https://ai.pydantic.dev/#why-use-pydanticai 示例代码 from pydantic_ai import Agent from pydantic_ai.models.openai import OpenAIModel from pydantic_ai.providers.openai import OpenAIProvider# 配置使用阿里云通义千问模型 model OpenAIMode…...
高抗扰度汽车光耦合器的特性
晶台光电推出的125℃光耦合器系列产品(包括KL357NU、KL3H7U和KL817U),专为高温环境下的汽车应用设计,具备以下核心优势和技术特点: 一、技术特性分析 高温稳定性 采用先进的LED技术和优化的IC设计,确保在…...
未授权访问事件频发,我们应当如何应对?
在当下,数据已成为企业和组织的核心资产,是推动业务发展、决策制定以及创新的关键驱动力。然而,未授权访问这一隐匿的安全威胁,正如同高悬的达摩克利斯之剑,时刻威胁着数据的安全,一旦触发,便可…...
