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版本原因造成的LocalDateTimeLocalDate等的类型转换失败问题。但类型转换失败有可能是数据库驱动、或连接池的版本问题造成的,实际开发过程中遇到过在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

❗版权声明
本文为原创文章,版权归作者所有。未经许可,禁止转载。更多内容请访问奇迹老李的博客首页

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/283307.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

linux下docker搭建Prometheus +SNMP Exporter +Grafana进行核心路由器交换机监控

一、安装 Docker 和 Docker Compose https://docs.docker.com/get-docker/ # 安装 Docker sudo apt-get update sudo apt-get install -y docker.io# 安装 Docker Compose sudo apt-get install -y docker-compose二、创建配置文件及测试平台是否正常 1、选个文件夹作为自建…

医学图像分割中的频域多轴表示学习

摘要 https://arxiv.org/pdf/2312.17030v1.pdf 最近&#xff0c;视觉Transformer (ViT)在医学图像分割&#xff08;MIS&#xff09;中得到了广泛应用&#xff0c;这归功于其在空间域应用自注意力机制来建模全局知识。然而&#xff0c;许多研究都侧重于改进空间域模型&#xff…

LeetCode刷题--- 不同路径 III

个人主页&#xff1a;元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏 力扣递归算法题 http://t.csdnimg.cn/yUl2I 【C】 ​​​​​​http://t.csdnimg.cn/6AbpV 数据结构与算法 ​​​http://t.csdnimg.cn/hKh2l 前言&#xff1a;这个专栏主要讲述递…

x-cmd pkg | gum - 很好看的终端 UI 命令行工具

目录 简介首次用户功能特点Bubbles 与 Lip Gloss进一步探索 简介 gum 由 Charm 组织于 2022 年使用 Go 语言开发。旨在帮助用户编写 Shell 脚本与 dotfiles 时提供一系列快捷使用&#xff0c;可配置&#xff0c;可交互&#xff0c;美观的 Terminal UI 组件。 首次用户 使用 x…

U4_3 语法分析-自底向上分析-LR0/LR1/SLR分析

文章目录 一、LR分析法1、概念2、流程3、LR分析器结构及分析表构造1&#xff09;结构2&#xff09;一些概念 二、LR(0)分析法1、流程2、分析动作1&#xff09;移近2&#xff09;归约(reduce) 3、总结1&#xff09;LR分析器2&#xff09;构造DFA3&#xff09;构造LR(0)的方法(三…

Apache SSI 远程命令执行漏洞

一、环境搭建 二、访问upload.php 三、写shell <!--#exec cmd"id" --> 四、访问 如图所示&#xff0c;即getshell成功&#xff01;​

K8s实战入门

1.NameSpace Namespace是kubernetes系统中的一种非常重要资源&#xff0c;它的主要作用是用来实现多套环境的资源隔离或者多租户的资源隔离。 默认情况下&#xff0c;kubernetes集群中的所有的Pod都是可以相互访问的。但是在实际中&#xff0c;可能不想让两个Pod之间进行互相…

C#线程基础(线程启动和停止)

目录 一、关于线程 二、示例 三、生成效果 一、关于线程 在使用多线程前要先引用命名空间System.Threading&#xff0c;引用命名空间后就可以在需要的地方方便地创建并使用线程。 创建线程对象的构造方法中使用了ThreadStart()委托&#xff0c;当线程开始执行时&#xff0c…

tp5+workman(GatewayWorker) 安装及使用

一、安装thinkphp5 1、宝塔删除php禁用函数putenv、pcntl_signal_dispatch、pcntl_wai、pcntl_signal、pcntl_alarm、pcntl_fork&#xff0c;执行安装命令。 composer create-project topthink/think5.0.* tp5 --prefer-dist 2、配置好站点之后&#xff0c;浏览器打开访问成…

Qt菜单工具栏和状态栏

QMenuBar 接口介绍 QAction 定义&#xff1a;QAction 是一个独立于具体界面元素的抽象动作表示。它封装了一个用户界面动作&#xff08;比如点击命令&#xff09;&#xff0c;通常与一个菜单项、工具栏按钮或快捷键相关联。用途&#xff1a;你可以将 QAction 视为一个可执行的…

解决Android Studio的adb命令行报错Permission denied问题-建议收藏备用!

目录 前言 一、报错信息 二、常见解决方法 三、最简单的解决方法 四、更多资源 前言 随着移动设备的普及&#xff0c;Android操作系统成为了全球最主要的移动设备操作系统之一。在开发和调试Android应用程序时&#xff0c;我们常常需要使用adb&#xff08;Android Debug B…

Resnet BatchNormalization 迁移学习

时间&#xff1a;2015 网络中的亮点&#xff1a; 超深的网络结构&#xff08;突破1000层&#xff09;提出residual模块使用Batch Normalization加速训练&#xff08;丢弃dropout&#xff09; 层数越深效果越好&#xff1f; 是什么样的原因导致更深的网络导致的训练效果更差呢…

云计算:OpenStack 分布式架构部署(单控制节点与多计算节点)

目录 一、实验 1.环境 2. 计算服务安装(计算节点2) 3. 网络服务安装(计算节点2) 一、实验 1.环境 (1) 主机 表1 主机 主机架构IP备注controller控制节点192.168.204.210已部署compute01计算节点1192.168.204.211 已部署compute02计算节点2192.168.204.212 &#xff08;…

如何下载Sentinel-1数据

Sentinel-1是欧洲空间局&#xff08;ESA&#xff09;的一组地球观测卫星&#xff0c;属于Copernicus计划的一部分。该计划旨在为全球环境监测提供数据&#xff0c;并支持应对气候变化、自然灾害和人类活动的挑战。Sentinel-1卫星的主要任务是提供全天候、全时段、高分辨率的合成…

C#-CSC编译环境搭建

一.Microsoft .NET Framework 确保系统中安装Microsoft .NET Framework相关版本下载 .NET Framework 4.7 | 免费官方下载 (microsoft.com)https://dotnet.microsoft.com/zh-cn/download/dotnet-framework/net47 二.编译环境搭建 已经集成编译工具csc.exe,归档至gitcode,实现us…

5G随身WiFi避坑,5G随身WiFi口碑推荐,5G随身WiFi避雷,5G随身WiFi好用吗?

第一、切忌盲目入坑&#xff0c;目前市面上的主流随身 WiFi都是4G网络&#xff0c;不支持5G&#xff0c;当一些只卖几十块的随身WiFi&#xff0c;商家告诉你是5G随身WiFi的时候&#xff0c;直接拉黑。随身WiFi芯片都上百了&#xff0c;设备才几十块&#xff0c;怎么可能&#x…

浅聊配置化-要不要实现动态表单

1、配置化的原则 配置化是一种抽象&#xff0c;把事物分成2类&#xff1a;不变的&#xff0c;可变的。 如果事物都是可变的&#xff0c;是无法实现配置化的。 配置化的根本在于找到不变的事物&#xff0c;基于不变的事物进行可变事物的配置。 所以&#xff0c;认为一切皆可…

老子的《道德经》透露,不努力反而更成功

人类生而自由&#xff0c;但到处都是枷锁。 永远不要怀疑经过慎思且足够投入的一小群人能否改变这个世界。事实上&#xff0c;只有他们才办得到。 优美灵魂的两个发展方向&#xff1a;崇拜道德的天才&#xff0c;对别人实行道德的判断。 一、道 《道德经》开始的名字是《老子…

数据结构:第7章:查找(复习)

目录 顺序查找&#xff1a; 折半查找&#xff1a; 二叉排序树&#xff1a; 4. (程序题) 平衡二叉树&#xff1a; 顺序查找&#xff1a; ASL 折半查找&#xff1a; 这里 j 表示 二叉查找树的第 j 层 二叉排序树&#xff1a; 二叉排序树&#xff08;Binary Search Tree&…

零知识证明(zk-SNARK)- groth16(一)

全称为 Zero-Knowledge Succinct Non-Interactive Argument of Knowledge&#xff0c;简洁非交互式零知识证明&#xff0c;简洁性使得运行该协议时&#xff0c;即便 statement 非常大&#xff0c;它的 proof 大小也仅有几百个bytes&#xff0c;并且验证一个 proof 的时间可以达…