MyBatis之枚举类型

2023-11-17

枚举可以让代码变得更为优雅,B格更高。

当然MyBatis也是支持枚举类型的啦。

首先,MyBatis内置了Enum的TypeHandler

TypeHandler Java类型 JDBC类型
EnumTypeHandler Enum VARCHAR或任何兼容字符串的类型,
存储的是枚举的名称(而不是索引)
EnumOrdinalTypeHandler Enum 任何兼容NUMERIC或DOUBLE类型
存储的是枚举的索引(而不是名称)

请着重理解 什么叫枚举的索引,什么叫枚举的名称:

//TODO 写一个例子

public enum Color {
	Red(10, "#FF0000"), Green(11, "#00FF00"), BlueGreen(12, "#00FF00");

	private int id;
	private String rgb;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getRgb() {
		return rgb;
	}

	public void setRgb(String rgb) {
		this.rgb = rgb;
	}

	private Color(int id, String rgb) {
		this.id = id;
		this.rgb = rgb;
	}

	public static void main(String[] args) {
		System.out.println("枚举的名称:[" + Color.Red.name() + "]");
		System.out.println("枚举的索引:[" + Color.Red.ordinal() + "]");
	}
}

#output

枚举的名称:[Red]
枚举的索引:[0]
注意,枚举 Sex中的id和rgb并不是所谓的名称和索引。枚举的名称和索引都是枚举类型本身定义的,开发者并不能对齐进行修改。Enum的源码中也将name和ordinal定义为final类型了。

    /**
     * The name of this enum constant, as declared in the enum declaration.
     * Most programmers should use the {@link #toString} method rather than
     * accessing this field.
     */
    private final String name;

    /**
     * The ordinal of this enumeration constant (its position
     * in the enum declaration, where the initial constant is assigned
     * an ordinal of zero).
     *
     * Most programmers will have no use for this field.  It is designed
     * for use by sophisticated enum-based data structures, such as
     * {@link java.util.EnumSet} and {@link java.util.EnumMap}.
     */
    private final int ordinal;

好了,开始正题。


本文主要测试了以下几点:

1.插入MyBatis枚举类型

2.读取MyBatis枚举类型

3.自定义一个枚举Handler


创建一个表:

CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `sex` int(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
)
这张表格有4个字段,显然,Sex,非男即女,可以使用枚举类型,定义一个枚举类型



定义枚举类型:

Sex


准备Mybatis基本使用的一些工具,具体可以看我之前的博客http://blog.csdn.net/tjzhuorui/article/details/66997291

好,现在有了MyBatis可以正常使用了,我可以通过SqlSessionFactoryUtil获取SqlSession了.


创建一个POJO,User

public class User {
	private int id;
	private String name;
	private Sex sex;
	private int age;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Sex getSex() {
		return sex;
	}

	public void setSex(Sex sex) {
		this.sex = sex;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
}

创建一个接口UserMapper,定义我们将对数据进行的操作:

public interface UserMapper {
	// 使用MyBatis自带的EnumOrdinalTypeHandler,数据库中对应的枚举字段应该为"数字型"
	int insertByEnumOrdinalTypeHandler(User user);
	User selectByEnumOrdinalTypeHandler(int id);

	// 使用MyBatis自带的insertByEnumTypeHandler,数据库中对应的枚举字段应该为"字符串型",本例中,不使用
	int insertByEnumTypeHandler(User user);
	User selectByEnumTypeHandler(int id);

	// 使用自定义的TypeHandler,来实现
	int insertByCustomerTypeHandler(User user);
	User selectByCustomerTypeHandler(int id);
}
然后,创建user-mapper.xml,并在mybatis-config.xml中关联user-mapper.xml

mybatis-config.xml

	<mappers>
		<mapper resource="com/robin/mapper/config/user-mapper.xml" />
	</mappers>


user-mapper.xml

<mapper namespace="com.robin.mapper.UserMapper">
	<insert id="insertByEnumOrdinalTypeHandler" parameterType="com.robin.pojo.User">
		insert into t_user
		(name,sex,age)values(#{name},#{sex,typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler},#{age})
	</insert>
</mapper>
然后测试类:

public class TestEnumOrdinalTypeHandler {

	public static void main(String[] args) {
		SqlSession session = null;
		try {
			session = SqlSessionFactoryUtil.getSqlSession();
			UserMapper mapper = session.getMapper(UserMapper.class);
			User user = new User();
			user.setSex(Sex.Male);
			user.setName("zhangsan");
			user.setAge(22);
			mapper.insertByEnumOrdinalTypeHandler(user);
			session.commit();
		} catch (Exception ex) {
			ex.printStackTrace();
			session.rollback();
		} finally {
			if (session != null)
				session.close();
		}

	}
}

ok,测试成功,能够看到日志输出:

2017-04-07 11:07:09,005 DEBUG [com.robin.mapper.UserMapper.insertByEnumOrdinalTypeHandler]
 ==>  Preparing: insert into t_user (name,sex,age)values(?,?,?)
2017-04-07 11:07:09,059 DEBUG [com.robin.mapper.UserMapper.insertByEnumOrdinalTypeHandler]
 ==> Parameters: zhangsan(String), 0(Integer), 22(Integer)
2017-04-07 11:07:09,061 DEBUG [com.robin.mapper.UserMapper.insertByEnumOrdinalTypeHandler]
 <==    Updates: 1
2017-04-07 11:07:09,062 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction]
 Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@5ce81285]

然后看数据库:

数据已经插入了。并且能够看到sex为0,id为11

现在读取id为11的数据。

修改user-map.xml,添加查询部分的配置:

	<resultMap type="com.robin.pojo.User" id="usermap1">
		<result column="id" property="id" />
		<result column="name" property="name" />
		<result column="sex" property="sex"
	typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler" />
		<result column="age" property="age" />
	</resultMap>
	<select id="selectByEnumOrdinalTypeHandler" parameterType="int"
		resultMap="usermap1">
		select id,name,sex,age from t_user where id=#{id}
	</select>
再添加,测试查询的部分:

public class TestEnumOrdinalTypeHandler {

	public static void main(String[] args) {
		SqlSession session = null;
		try {
			session = SqlSessionFactoryUtil.getSqlSession();
			UserMapper mapper = session.getMapper(UserMapper.class);
			// testInsert(session, mapper);
			int id = 11;
			testSelectOne(session, mapper, id);

			session.commit();
		} catch (Exception ex) {
			ex.printStackTrace();
			session.rollback();
		} finally {
			if (session != null)
				session.close();
		}
	}

	private static void testSelectOne(SqlSession session, UserMapper mapper,
			int id) {
		User user = mapper.selectByEnumOrdinalTypeHandler(id);
		System.out.println(user);

	}

	private static void testInsert(SqlSession session, UserMapper mapper) {
		User user = new User();
		user.setSex(Sex.Male);
		user.setName("zhangsan");
		user.setAge(22);
		mapper.insertByEnumOrdinalTypeHandler(user);
	}
}
得出结果:User [id=11, name=zhangsan, sex=Male, age=22]。

ok结束,那么现在我有的新的需求:

现在我改变定义了,男人是用10表示,女人是用100表示;并且在查询的时候,如果sex字段是10显示男,如果是100显示女,其他字段,返回null;

回顾一下,Mybatis自带的枚举TypeHandler显然已经无法满足我们的需求了,那么现在我们就需要自定义TypeHandler了。

重新定义一下Sex:

public enum Sex {
	Male(10, "男"), Female(100, "女");

	private int tag;
	private String desc;

	public String getDesc() {
		return desc;
	}

	public int getTag() {
		return tag;
	}

	public void setTag(int tag) {
		this.tag = tag;
	}

	public void setDesc(String desc) {
		this.desc = desc;
	}

	private Sex(int tag, String desc) {
		this.tag = tag;
		this.desc = desc;
	}
}
可以看到的是,添加了一个tag和的desc.

然后,自定义MyEnumSexTypeHandler implements TypeHandler<Sex>

public class MyEnumSexTypeHandler implements TypeHandler<Sex> {

	@Override
	public Sex getResult(ResultSet rs, String columnName) throws SQLException {
		int tag = rs.getInt(columnName);
		for (Sex sex : Sex.values()) {
			if (sex.getTag() == tag)
				return sex;
		}
		return null;
	}

	@Override
	public Sex getResult(ResultSet rs, int columnIndex) throws SQLException {
		int tag = rs.getInt(columnIndex);
		for (Sex sex : Sex.values()) {
			if (sex.getTag() == tag)
				return sex;
		}
		return null;
	}

	@Override
	public Sex getResult(CallableStatement cs, int columnIndex)
			throws SQLException {
		int tag = cs.getInt(columnIndex);
		for (Sex sex : Sex.values()) {
			if (sex.getTag() == tag)
				return sex;
		}
		return null;
	}

	@Override
	public void setParameter(PreparedStatement pstmt, int index, Sex sex,
			JdbcType jdbcType) throws SQLException {
		pstmt.setInt(index, sex.getTag());// 这里,不在是使用Sex的oridinal了
	}

}
然后在mybatis-config.xml中,注册MyEnumSexTypeHandler

    <typeHandlers>
        <typeHandler handler="com.robin.type.custom.MyEnumSexTypeHandler" />
    </typeHandlers>

然后在user-mapper.xml中,配置sql语句

	<insert id="insertByCustomerTypeHandler" parameterType="com.robin.pojo.User">
		insert
		into t_user
		(name,sex,age)values(#{name},#{sex,typeHandler=com.robin.type.custom.MyEnumSexTypeHandler},#{age})
	</insert>

最后,写测试类:

public class TestCustomEnumTypeHandler {
	public static void main(String[] args) {
		SqlSession session = null;
		try {
			session = SqlSessionFactoryUtil.getSqlSession();
			UserMapper mapper = session.getMapper(UserMapper.class);
			testInsert(session, mapper);
			// int id = 11;
			// testSelectOne(session, mapper, id);

			session.commit();
		} catch (Exception ex) {
			ex.printStackTrace();
			session.rollback();
		} finally {
			if (session != null)
				session.close();
		}
	}

	private static void testInsert(SqlSession session, UserMapper mapper) {
		User user = new User();
		user.setName("wang55");
		user.setAge(99);
		user.setSex(Sex.Female);
		mapper.insertByCustomerTypeHandler(user);

	}
}

运行,然后看到数据库中确实插入了:

注意看sex,是不是100呀,ok,这样就满足我们的需求了。

关于查询,与MyBatis自带的EnumOrdinalTypeHandler类似,这里,笔者就不粘贴了。感兴趣可以自己去试试。













本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MyBatis之枚举类型 的相关文章

随机推荐

  • spring boot 1.5.4 之监控Actuator(十四)

    上一篇 spring boot 1 5 4 整合 druid 十三 Spring Boot监控Actuator 项目 mybatis spring boot为例 源码地址 spring boot相关项目源码 码云地址 https git o
  • Spring 启动错误:ConfigServletWebServerApplicationContext

    报错提示 2023 02 14 14 28 07 198 INFO 15724 main com longyi ruiji RuiJiApplication Starting RuiJiApplication using Java 19 0
  • QT绘图:实现将没有布局的界面进行缩放显示

    QT绘图 实现将没有布局的界面进行缩放显示 前言 在实际开发过程中 会遇到一些无法使用布局的界面 如果将这样的界面直接放入另一个界面 大小不合适就会出现页面太丑的情况 而解决的方法可以是重构界面 但是一些界面过于复杂 重构很难实现 那么笔者
  • 用MATLAB对图像进行采样处理

    用MATLAB对图像进行采样处理 一 实验目的 掌握图像采样原理 二 实验内容 试对512x512的lenagray jpg图像分别采样为256x256 128x128 64x64的图像 观察图像质量的变化 第一幅图是原图 第二幅是不同采样
  • linux下手动安装git教程

    Git是一个开源的分布式版本控制系统 可以有效 高速的处理从很小到非常大的项目版本管理 而国外的GitHub和国内的Coding都是项目的托管平台 但是在使用git工具的时候 第一步要学会如何安装git 本教程就手把手教大家如何手动编译安装
  • input的type=file触发的相关事件

    今天突然用到input相关的事件 突然发现自己还没有总结过input相关事件的运行原理 而且我还竟然翻api去了解了 所以 为了记恨自己 就写了相关与input相关的事件运行的过程 添加了一些相关的方法测试了一下 这一节首先介绍一个inpu
  • mysql 修改utf8mb4

    右键计算机 找到服务和应用程序 找到服务 找到MYSQL56 img src https img blog csdn net 20160518101645822 watermark 2 text aHR0cDovL2Jsb2cuY3Nkbi
  • C++ 浮点数的大小比较

    C 浮点数的大小比较 一 C 的精度损失 二 浮点数比较 三 总结 一 C 的精度损失 浮点数的存储格式 符号位 指数位 尾数位 sign bit Exponent Mantissa 浮点数分为单精度float和双精度double 32位和
  • WordPress search页面出现 404

    遇到问题 在新版 6 0 2 发现 当使用 wordpress 提供的原生searchform php搜索功能时 会出现 404 报错信息 导致界面样式错乱 问题排查 从请求发现 使用原生搜索组件 发出的请求是在根路由后面直接拼接了 s x
  • TCP滑动窗口控制流量的原理

    TCP的滑动窗口机制 TCP这个协议是网络中使用的比较广泛 他是一个面向连接的可靠的传输协议 既然是一个可靠的传输协议就需要对数据进行确认 TCP协议里窗口机制有2种 一种是固定的窗口大小 一种是滑动的窗口 这个窗口大小就是我们一次传输几个
  • 浏览器识别操作系统

    前端识别操作系统 浏览器识别操作系统 软件设计模式概述 浏览器识别操作系统
  • thread_Timer(线程中定时器)

    package com gzhs zsd thread import java util Date import java util Timer import java util TimerTask Timer定时器运用 author 谢泽
  • java 支付宝红包接入

    1 将公钥验证升级为证书验证 会得到如下三个证书 2 配置文件相关 支付宝支付相关配置 alipayconfig appid pid app private key charset utf 8 alipay public key call
  • Ubuntu 提示 Could not get lock /var/lib/dpkg/lock-frontend.解决方法

    今天在Ubuntu上安装的达梦数据库出现了一点操作错误 进行删除后还原快照就出现了这个问题 当我进行 apt 源安装还有更新时就一直显示 Waiting for cache lock Could not get lock var lib d
  • 解决VScode代码注释异常高亮

    问题描述 VScode出现代码注释后仍然高亮的问题 或者定义的函数名或者关键词没有高亮 如下所示 正常情况 异常情况 原因分析 同时装了python的扩展和vscode for python的扩展导致 两个扩展的主题配色冲突 解决方案 卸载
  • unity之InputField的文本监听

    1 创建InputField creat gt UI gt InputField 2 基本属性界面 可以再content type属性下设置InputField的文本类型 图片中无显示 3 文本监听 创建脚本 代码如下 using Syst
  • 计算机视觉————目标检测,多尺度问题理解以及FCN(全卷积神经网络)存在的弊端,问题。

    在阅读文献中 通常会遇到一个名词 XX用来解决多尺度问题 多尺度问题是什么意思 目标检测中 我们希望对于输入图片 不管图片中某个目标或大或小 我们都需要将其识别 对于小物体 我们可以将其理解为两种方式 一种是绝对小物体 即它本身占的像素就比
  • Android.bp 语法浅析-Android10.0编译系统(八)

    Android取经之路 的源码都基于Android Q 10 0 进行分析 Android取经之路 系列文章 系统启动篇 Android系统架构Android是怎么启动的Android 10 0系统启动之init进程Android10 0系
  • mysql怎么创建出生日期表_MySQL表的创建

    第1步 设计 首先要设计一张用于我想要用途的表 例如如下用于描述个人的信息类型 姓名 性别 出生日期 地址 最喜爱的食物 下面为他来指定列和数据类型 列 类型 允许值 name varchar 40 gender char 1 M F bi
  • MyBatis之枚举类型

    枚举可以让代码变得更为优雅 B格更高 当然MyBatis也是支持枚举类型的啦 首先 MyBatis内置了Enum的TypeHandler TypeHandler Java类型 JDBC类型 EnumTypeHandler Enum VARC