场景:

MySQL里的某一个字段,比如:status状态,一共有5个状态,我们会在MySQL里 建立 status(int)字段,1、2、3、4、5 来标记5种状态;利用MyBatis在自动代码生成器生成实体类后,status会是integer类型;

而status 只有5种状态,且程序很多地方常用,于是我们建立status枚举,返回给终端的json里,也是返回枚举字符串,只是存MySQL里用int来存,节省空间,提升查询效率;好了多余的废话不说了,直接上代码:

1. 建立一个通用的枚举接口:

/**
* MySQL字段对应的枚举类需要实现这个接口
*/
public interface ISqlEnum { /**
* 获取对应的MySQL里的值
*/
Integer getSqlInt();
}

2.定义一个枚举,实现枚举接口:

/**
* 平台类型,以后尽量使用这个来取代ShopType,枚举类;
* ShopType会等待合适的时机变更为:平台内部店铺类型如:专营店、自营店、旗舰店等
*/
public enum PlatformType implements ISqlEnum { OFFLINE("线下", 9), /**
* 淘宝/天猫
*/
TAOBAO("淘宝/天猫", 1), /**
* 京东
*/
JINGDONG("京东", 2), /**
* 拼多多
*/
PINDUODUO("拼多多", 3), /**
* 抖音
*/
DOUYIN("抖音", 4), /**
* 微信视频号
*/
WEIXIN("微信视频号", 5), /**
* 阿里1688
*/
ALI1688("阿里1688", 6), /**
* 快手
*/
KUAISHOU("快手", 7), /**
* 苏宁
*/
SUNING("苏宁", 8); /**
* 线下
*/ /**
* 店铺类型的英文名称就是枚举的小写,中文名称存储一下,方便直接返回给客户端;
*/
private String cnName; /**
* MySQL里的int值
* 平台类型:1(淘宝),2(京东),3(拼多多),4(抖音),5(微信视频号),6(阿里1688),7(快手),8(苏宁),9(线下)
*/
private Integer sqlInt; /**
* 私有构造方法
*/
private PlatformType(String cnName, Integer sqlInt) {
this.cnName = cnName;
this.sqlInt = sqlInt;
} /**
* 对外公开获取中文名称的方法
*/
public String getCnName(){
return this.cnName;
} @Override
public Integer getSqlInt() {
return this.sqlInt;
} }

3. 定义一个类型处理器:类型处理器(typeHandlers),根据mybatis官方的文档,它默认已经有了2个枚举类型处理器:https://mybatis.net.cn/configuration.html#typeHandlers

A. EnumTypeHandler 这个官方默认的,通过官方的说明,源码得出结论:就是说 你MySQL里 若这个status字段是varchar类型,你向MySQL里存的是枚举的字符串的话,举例:PlatformType.TAOBAO,

你向MySQL里 存的是 TAOBAO 这个字符串的话,那么你可以直接在实体类里使用PlatformType枚举,而不用再做任何操作,因为TAOBAO这个字符串是可以直接与枚举类互转的;

B. EnumOrdinalTypeHandler 这个官方默认的,意思是:若你向MySQL里存的是枚举类的序号值,MySQL里是int 或兼容int的类型,也是不用做任何操作,在实体类里就可以使用 这个枚举;

因为序号也是可以直接与枚举互转的;

官方能做的也就A,B这2个了,其它的官方的也无能为力,A 首先不合适,正如官网所说,我们的DBA更倾向于枚举字段,在MySQL里用 int 类型来存储,节省空间,提升查询效率;

接下来说下B,B虽然MySQL里存的是int了,但是也太简陋了,只能按枚举的序号来,那么就意味着枚举类里的顺序 TAOBAO,JINGDONG,PDD你不能改变,一旦变成DOUYIN,TAOBAO,JINGDONG,PDD

则会出大乱子了!所以B还是简陋了,适合刚设计时就永远不会发生变化的枚举类;

细想你会发现官方能做的也只能这样了,因为枚举类是你自由定义的,要想 MySQL -- 枚举类,枚举类 --> Mysql;官方能做的就是 通过默认的字符串和 序号来转化,其它的转化是你自己自定义的,官方又如何能知道呢;

根据官方的提示,我们参考 官方默认的 两个枚举处理器,自定义一个我们自己的泛型枚举处理器;

public class SqlEnumHandler<E extends SqlEnum> extends BaseTypeHandler<E> {

    /**
* 把枚举实例存入map,而不是官方的数组,因为数组查找的时候需要遍历,
* 官方使用数组是因为官方按枚举序号来的,即使使用数组也不需要遍历,
* 而我们不一定,sqlInt我们是自定义的,不是枚举实例的序号;
*/
private final Map<Integer, E> enumMap; /**
* 官方的框架会自动调用这个方法,来构建枚举实例map
*/
public SqlEnumHandler(Class<E> type) {
if (type == null) {
throw new IllegalArgumentException("Type argument cannot be null");
}
//拿到类型实例,写入map
enumMap = new HashMap<>();
for (E enumConstant : type.getEnumConstants()) {
enumMap.put(enumConstant.getSqlInt(), enumConstant);
}
} /**
* 1.若MySQL里的字段设置了不为Null,而你传入的枚举是Null,那么应该如何写入MySQL;(这个由你写代码决定,就是本方法)
* 2.若MySQL里的字段设置了可以为Null,而你传入的枚举也是Null,这种官方自动处理了,自动写入Null,不需要你写额外的代码;
* --------------------------------------------------------------
* 我们强制规定,若MySQL里一个字段是枚举,则这个字段【必须】设置成不为Null;
* 因为MySQL层面的问题,要在MySQL层面解决,举例:status都已经是一个枚举字段了,一共就5种状态,
* 是定死的,你非要搞成可以null,这就是你自己的脑袋有问题;我们这里不考虑Null的问题;
*/
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
ps.setInt(i, parameter.getSqlInt());
} /**
* 1.若MySQL里字段设置了可以为Null,当查询出来的结果为Null,你要转成哪个枚举实例;(需要你写代码来决定,就是本方法)
* 2.若MySQL里字段设置了可以为Null,查询出来的结果不为Null,这种的也需要你写代码来决定,就是本方法;
* -----------------------------
* 我们强制MySQL里的枚举字段不可以为Null,所以不考虑Null的问题,以下都是同理;
*/
@Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
return enumMap.get(rs.getInt(columnName));
} @Override
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return enumMap.get(rs.getInt(columnIndex));
} @Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return enumMap.get(cs.getInt(columnIndex));
}
}

使用接口的话,也行,我们使用的是接口:

/**
* mybatis枚举类型处理器
*/
public class SqlEnumHandler<E extends SqlEnum> implements TypeHandler<E> { /**
* 把枚举实例存入Map
*/
private final Map<Integer, E> enumMap; /**
* 根据枚举类型构建Map
*/
public SqlEnumHandler(Class<E> type) {
if (type == null) {
throw new IllegalArgumentException("Type argument cannot be null");
}
//拿到类型实例,写入map
enumMap = new HashMap<>();
for (E enumConstant : type.getEnumConstants()) {
enumMap.put(enumConstant.getSqlInt(), enumConstant);
}
} /**
* Java枚举 ---写入---> MySQL Int
*/
@Override
public void setParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
ps.setInt(i, parameter.getSqlInt());
} /**
* MySQL Int ---读取---> Java枚举
* 强制规定:此MySQL字段必须设置成不为Null,因为MySQL层面的问题,要在MySQL层面解决,
* 举例:status都已经是一个枚举字段了,一共就5种状态,是定死的,若MySQL里允许为Null,
* 这就是开发者有问题,需要去修复MySQL,而不是在这里处理Null;这里不考虑Null的问题;
*/
@Override
public E getResult(ResultSet rs, String columnName) throws SQLException {
return enumMap.get(rs.getInt(columnName));
} @Override
public E getResult(ResultSet rs, int columnIndex) throws SQLException {
return enumMap.get(rs.getInt(columnIndex));
} @Override
public E getResult(CallableStatement cs, int columnIndex) throws SQLException {
return enumMap.get(cs.getInt(columnIndex));
}
}

4. spring boot 的 application.properties 加上配置,配置一下枚举类型处理器,你会发现spring boot 会有这个配置,原因是为什么呢,肯定是mybatis官方也知道他提供的那2个枚举类型处理器,弱爆了,

而这个处理器,只能由用户自己来编写代码,所以他有一个配置来让你指定;

#你指定一下你自己写的那个SqlEnumHandler类就行了;
mybatis.configuration.default-enum-type-handler

================================

以上4步搞定后,就可以了,测试:

SpringBoot-MyBatis - Java枚举类型 <---> MySQL Int,建立 类型处理器(typeHandlers)的更多相关文章

  1. java中存储mysql数据库时间类型

    Mysql 与 java 的时间类型 MySql的时间类型有 Java中与之对应的时间类型   date                 java.sql.Date   Datetime        ...

  2. springboot mybatis自定义枚举enum转换

    原文链接:https://blog.csdn.net/u014527058/article/details/62883573 一.概述 在利用Spring进行Web后台开发时,经常会遇到枚举类型的绑定 ...

  3. springboot+mybatis集成多数据源MySQL/Oracle/SqlServer

    日常开发中可能时常会遇到一些这样的需求,业务数据库和第三方数据库,两个或多个数据库属于不同数据库厂商,这时候就需要通过配置来实现对数据库实现多源处理.大致说一下我的业务场景,框架本身是配置的sprin ...

  4. mysql int 整数类型 解释显示宽度 和 存储宽度

    存储宽度 是实际存储记录宽度 存储宽度默认是写死的,就算修改宽度也改变不了,改变的是显示宽度 ============有符号和无符号int============= 创建一个 无符号的 int 整数类 ...

  5. spring boot1.1 idea + springboot + mybatis(mybatis-generator) +mysql +html实现简单的登录注册

    前言 这两年springboot比较火,而我平时的工作中不怎么使用spring boot,所以工作之余就自己写写项目练练手,也跟大家一起学习. 打算从最开始的搭架子,登录注册,到后台管理的增删改查,业 ...

  6. springboot + mybatis 支持oracle和mysql切换含源码

    1.springboot 启动类加入bean 如下 // DatabaseIdProvider元素主要是为了支持不同的数据库@Beanpublic DatabaseIdProvider getData ...

  7. java中存储mysql数据库时间类型【date、time、datetime、timestamp】

    在MySQL中对于时间的存储自己见表的时候都是设置的varchar类型的,感觉挺方便的. 昨天拿别人建好的表写代码,发现这张表中时间类型为datetime的,凭感觉试了一下不行,网上查了刚开始试了好几 ...

  8. 将String类型转换为int整数类型

    示例如下: public class demo { public static void main(String[] args) { String s="10"; 6 7 //St ...

  9. MyBatis(八):Mybatis Java API枚举类型转化的用法

    最近工作中用到了mybatis的Java API方式进行开发,顺便也整理下该功能的用法,接下来会针对基本部分进行学习: 1)Java API处理一对多.多对一的用法: 2)增.删.改.查的用法: 3) ...

  10. 扩展mybatis和通用mapper,支持mysql的geometry类型字段

    因项目中需要用到地理位置信息的存储.查询.计算等,经过研究决定使用mysql(5.7版本)数据库的geometry类型字段来保存地理位置坐标,使用虚拟列(Virtual Generated Colum ...

随机推荐

  1. 编写Java代码时应该避免的6个坑

    通常情况下,我们都希望我们的代码是高效和兼容的,但是实际情况下代码中常常含有一些隐藏的坑,只有等出现异常时我们才会去解决它.本文是一篇比较简短的文章,列出了开发人员在编写 Java 程序时常犯的错误, ...

  2. BTC-协议

    BTC-协议 一个去中心化的数字货币要解决两个问题 1.谁有权发行货币 比特币的发行是由挖矿决定的(coinbase transaction 唯一一个产生新币的途径)比特币通过挖矿来决定货币的发行权, ...

  3. WebApi的输出结果重写 OnActionExecuted

    public override void OnActionExecuted(ActionExecutedContext context) { if (context.Exception != null ...

  4. spring——DI_依赖注入

    Spring的注入方式 Dependency Injection 概念 依赖注入(Dependency Injection) 依赖:指Bean对象的创建依赖于容器,Bean对象的依赖资源 注入:指Be ...

  5. [转帖]字符集 AL32UTF8 和 UTF8

    https://blog.51cto.com/comtv/383254# 文章标签职场休闲字符集 AL32UTF8 和 UTF8文章分类数据库阅读数1992 The difference betwee ...

  6. JVM大页内存的学习与使用

    JVM大页内存的学习与使用 原理和背景 操作系统是计算机的重要组成部分. 现代的操作系统一般都采用 段页式内存管理. 段一般是为了管理和权限 页主要是为了虚拟内存和物理内存的映射. 分页管理可以让物理 ...

  7. [转帖]GB18030 编码

    https://www.qqxiuzi.cn/zh/hanzi-gb18030-bianma.php GB18030编码采用单字节.双字节.四字节分段编码方案,具体码位见下文.GB18030向下兼容G ...

  8. [转帖]使用 Dumpling 导出数据

      16 Contributors 使用数据导出工具 Dumpling,你可以把存储在 TiDB 或 MySQL 中的数据导出为 SQL 或 CSV 格式,用于逻辑全量备份.Dumpling 也支持将 ...

  9. [转帖]《Linux性能优化实战》笔记(十七)—— Linux网络基础与性能指标

    一. 网络模型 1. OSI 网络模型(七层) 为了解决网络互联中异构设备的兼容性问题,并解耦复杂的网络包处理流程,OSI 模型把网络互联的框架分为七层,每个层负责不同的功能.其中, 应用层,负责为应 ...

  10. 【转帖】【ethtool】ethtool 网卡诊断、调整工具、网卡性能优化| 解决丢包严重

    目录 即看即用 详细信息 软件简介 安装 ethtool的使用 输出详解 其他指令 将 ethtool 设置永久保存 如何使用 ethtool 优化 Linux 虚拟机网卡性能 ethtool 解决网 ...