Mybatis枚举类型处理和类型处理器

专栏精选

引入Mybatis

Mybatis的快速入门

Mybatis的增删改查扩展功能说明

mapper映射的参数和结果

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CNN实现对手写字体的迭代

导入库 import torchvision import torch from torchvision.transforms import ToTensor from torch import nn import matplotlib.pyplot as plt 导入手写字体数据 train_dstorchvision.datasets.MNIST(data/,trainTrue,transformToTensor(),downloadTrue) test_dstorchvis…

CSDN被关注自动回复消息怎么设置

CSDN被关注自动回复消息怎么设置 1.鼠标移动到头像 2.点击内容管理 3.拉到下面&#xff0c;看到工具目录&#xff0c;里面有个粉丝服务点击 4.点击自动回复 5.这里点击打开&#xff0c;选择被关注自动回复&#xff0c;设置文字或图片点击保存就好了

SDRAM小项目——uart发送模块

数据的输入&#xff1a; 数据的输入是uart接收模块的输出&#xff1a;串—并—串&#xff08;接收到的外部的串行数据进入内部寄存器转化为并行数据&#xff0c;再由内部寄存器读出&#xff0c;输出表现为串行数据&#xff09;&#xff0c;接收到的输入信号为tx_flag&#xff0…

【机组期末速成】计算机的运算方法|进制转换|无符号数与有符号数|数的定点表示与浮点表示|定点运算

&#x1f3a5; 个人主页&#xff1a;深鱼~&#x1f525;收录专栏&#xff1a;计算机组成原理&#x1f304;欢迎 &#x1f44d;点赞✍评论⭐收藏 目录 前言&#xff1a; 一、本章考点总览 二、考点分析 1、日常我们采用十进制来表示数据&#xff0c;计算机如何表示&#xf…

24、Qt使用QCustomPlot

一、下载文件 进入官网&#xff0c;选择“Download”、QCustomPlot.tar.gz Qt Plotting Widget QCustomPlot - Download 二、创建项目 创建一个"Qt Widget Application"项目&#xff0c;基类选择“QMainWindow”&#xff0c;把刚才下载的压缩包里的“qcustomplot.…

K8S网络类型

k8s的网络类型 k8s的通信模式 1 pod内部之间容器与容器之间的通信&#xff0c;在同一个pod中容器是共享资源和网络&#xff0c;使用同一个网络命名空间&#xff0c;可以直接通信 2 同一个node节点之内&#xff0c;不同pod之间的通信&#xff0c;每个pod都有一个全局的真实ip地…

美国Top科技公司年薪大曝光,OpenAI 600万高居榜首!

全美顶尖AI公司年薪大曝光&#xff01; OpenAI 600万高居榜首&#xff0c;微软、英伟达只有OpenAI 的一半。 近日&#xff0c;美国一家帮助博士生协商薪资的公司Rora发布了一份薪资报告&#xff0c;公布了这些顶尖AI公司给研究人员开出的平均薪水。 以下是部分顶级AI公司的名…

数据结构和算法-B树(B树的查找 B树的最大高度和最小高度)

文章目录 回顾&#xff1a;二叉查找树五叉查找树如何查找查找成功查找失败如何保证查找效率 B树B树的高度小结 回顾&#xff1a;二叉查找树 五叉查找树 进一步对范围划分&#xff0c;处于不同划分进入不同子树 四个数做划分&#xff0c;此时有五个区间 此时一个节点对应多个关…

[RoarCTF2019] TankGame

不多说&#xff0c;用dnspy反编译data文件夹中的Assembly-CSharp文件 使用分析器分析一下可疑的FlagText 发现其在WinGame中被调用&#xff0c;跟进WinGame函数 public static void WinGame(){if (!MapManager.winGame && (MapManager.nDestroyNum 4 || MapManager.n…

基于javaWeb的图书馆管理系统

概述 基于Spring Spring MVC MyBatis的图书馆管理系统&#xff0c;使用Maven进行包管理。主要功能包括&#xff1a;图书查询、图书管理、图书编辑、读者管理、图书的借阅与归还以及借还日志记录等。 环境配置 开发环境&#xff1a;IDEA &#xff0c;mysql5.7&#xff0c;m…

leaflet学习笔记-初始化vue项目(一)

leaflet简介 Leaflet是一款开源的轻量级交互式地图可视化JavaScript库&#xff0c;能够满足大多数开发者的地图可视化需求&#xff0c;其最早的版本大小仅仅38 KB。Leaflet能够在主流的计算机或移动设备上高效运行&#xff0c;其功能可通过插件进行扩展&#xff0c;拥有易于使用…

2023年房产赛道短视频平台营销观察

我国房地产经历20年的高速发展时期&#xff0c;地产相关从业人员依靠传统带看售楼处就能有相当规模的人流量&#xff0c;热门项目开盘可日销百套。 疫情三年&#xff0c;购房者的信息获取的习惯从线下踩盘变成线上观看短视频/直播&#xff0c;房企也越来越重视线上销售、抖音直…