1. 明确需求

在设计之初,sys_role表的enabled字段有2个可选值,其中0 代表禁用,1代表启用,而且实体类中我们使用的是Interger类型:

/*** 有效标志*/
private Integer enabled;public Integer getEnabled() {return enabled;
}public void setEnabled(Integer enabled) {this.enabled = enabled;
}

如果要新增或者更新角色信息,我们肯定要校验enabled字段的值必须是0或者1,所以最初的部分代码可能是这样的:

if (sysRole.getEnabled() == 0 || sysRole.getEnabled() == 1) {sysRoleMapper.updateById(sysRole);sysRole = sysRoleMapper.selectById(2L);Assert.assertEquals(0, sysRole.getEnabled());
} else {throw new Exception("无效的enabled值");
}

这种硬编码的方式不仅看起来不友好,而且不利于后期维护,如果维护的程序员脾气不好,还会骂你,哈哈。

所以我们的需求就是,拒绝硬编码,使用友好的编码方式来校验enabled字段的值是否有效。

2. 使用MyBatis提供的枚举类型处理器

我们通常会使用枚举来解决这种场景。

首先新建com.zwwhnly.mybatisaction.type包,然后在该包下新建枚举Enabled:

package com.zwwhnly.mybatisaction.type;public enum Enabled {/*** 禁用*/disabled,/*** 启用*/enabled;
}

其中,disabled对应的索引为0,enabled对应的索引为1。

然后将SysRole类中原来为Integer类型的enabled字段修改为:

/*** 有效标志*/
private Enabled enabled;public Enabled getEnabled() {return enabled;
}public void setEnabled(Enabled enabled) {this.enabled = enabled;
}

此时原本硬编码的代码就可以修改为:

if (sysRole.getEnabled() == Enabled.disabled || sysRole.getEnabled() == Enabled.enabled) {sysRoleMapper.updateById(sysRole);sysRole = sysRoleMapper.selectById(2L);Assert.assertEquals(Enabled.disabled, sysRole.getEnabled());
} else {throw new Exception("无效的enabled值");
}

虽然上面的代码很完美的解决了硬编码的问题,但此时又引出一个新的问题:

数据库并不能识别Enabled枚举类型,在新增,更新或者作为查询条件时,需要将枚举值转换为数据库中的int类型,在查询数据时,需要将数据库的int类型的值转换为Enabled枚举类型。

带着这个问题,我们在SysRoleMapperTest测试类中添加如下测试方法:

@Test
public void testUpdateById() {SqlSession sqlSession = getSqlSession();try {SysRoleMapper sysRoleMapper = sqlSession.getMapper(SysRoleMapper.class);// 先查询出id=2的角色,然后修改角色的enabled值为disabledSysRole sysRole = sysRoleMapper.selectById(2L);Assert.assertEquals(Enabled.enabled, sysRole.getEnabled());// 修改角色的enabled为disabledsysRole.setEnabled(Enabled.disabled);if (sysRole.getEnabled() == Enabled.disabled || sysRole.getEnabled() == Enabled.enabled) {sysRoleMapper.updateById(sysRole);sysRole = sysRoleMapper.selectById(2L);Assert.assertEquals(Enabled.disabled, sysRole.getEnabled());} else {throw new Exception("无效的enabled值");}} catch (Exception e) {e.printStackTrace();} finally {sqlSession.close();}
}

运行测试代码,发现抛出如下异常:

Error querying database. Cause: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'enabled' from result set. Cause: java.lang.IllegalArgumentException: No enum constant com.zwwhnly.mybatisaction.type.Enabled.1

这是因为MyBatis在处理Java类型和数据库类型时,使用TypeHandler(类型处理器)对这两者进行转换。

MyBatis为Java类型和数据库JDBC中的常用类型类型提供了TypeHandler接口的实现。

MyBatis在启动时会加载所有的JDBC对应的类型处理器,在处理枚举类型时默认使用org.apache.ibatis.type.EnumTypeHandler处理器,这个处理器会将枚举类型转换为字符串类型的字面值使用,对于Enabled枚举来说,就是“disabled"和”enabled"字符串。

而数据库中enabled字段的类型是int,所以在查询到角色信息将int类型的值1转换为Enabled类型报错。

那么如何解决这个问题呢?

MyBatis还提供了另一个枚举处理器:org.apache.ibatis.type.EnumOrdinalTypeHandler,这个处理器使用枚举的索引进行处理,可以解决此处转换报错的问题。

使用这个处理器,需要在之前的resources/mybatis-config.xml中添加如下配置:

<typeHandlers><typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"javaType="com.zwwhnly.mybatisaction.type.Enabled"/>
</typeHandlers>

再次运行测试代码,测试通过,输出日志如下:

DEBUG [main] - ==> Preparing: SELECT id,role_name,enabled,create_by,create_time FROM sys_role WHERE id = ?DEBUG [main] - ==> Parameters: 2(Long)TRACE [main] - <== Columns: id, role_name, enabled, create_by, create_timeTRACE [main] - <== Row: 2, 普通用户, 1, 1, 2019-06-27 18:21:12.0DEBUG [main] - <== Total: 1DEBUG [main] - ==> Preparing: UPDATE sys_role SET role_name = ?,enabled = ?,create_by=?, create_time=? WHERE id=?DEBUG [main] - ==> Parameters: 普通用户(String), 0(Integer), 1(Long), 2019-06-27 18:21:12.0(Timestamp), 2(Long)DEBUG [main] - <== Updates: 1

从日志中可以看出,在查询角色信息时,MyBatis将1转换为了Enabled.enabled,在更新角色信息时,MyBatis将Enabled.disabled转换为了0。

3. 使用自定义的类型处理器

假设enabled字段的值既不是枚举的字面值,也不是枚举的索引值,此时org.apache.ibatis.type.EnumTypeHandlerorg.apache.ibatis.type.EnumOrdinalTypeHandler都不能满足我们的需求,这种情况下我们就需要自己来实现类型处理器了。

首先修改下枚举类Enabled代码:

package com.zwwhnly.mybatisaction.type;public enum Enabled {/*** 启用*/enabled(1),/*** 禁用*/disabled(0);private final int value;private Enabled(int value) {this.value = value;}public int getValue() {return value;}
}

然后在com.zwwhnly.mybatisaction.type包下新建类型处理器EnabledTypeHandler:

package com.zwwhnly.mybatisaction.type;import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;/*** Enabled类型处理器*/
public class EnabledTypeHandler implements TypeHandler<Enabled> {private final Map<Integer, Enabled> enabledMap = new HashMap<Integer, Enabled>();public EnabledTypeHandler() {for (Enabled enabled : Enabled.values()) {enabledMap.put(enabled.getValue(), enabled);}}@Overridepublic void setParameter(PreparedStatement preparedStatement, int i, Enabled enabled, JdbcType jdbcType) throws SQLException {preparedStatement.setInt(i, enabled.getValue());}@Overridepublic Enabled getResult(ResultSet resultSet, String s) throws SQLException {Integer value = resultSet.getInt(s);return enabledMap.get(value);}@Overridepublic Enabled getResult(ResultSet resultSet, int i) throws SQLException {Integer value = resultSet.getInt(i);return enabledMap.get(value);}@Overridepublic Enabled getResult(CallableStatement callableStatement, int i) throws SQLException {Integer value = callableStatement.getInt(i);return enabledMap.get(value);}
}

自定义类型处理器实现了TypeHandler接口,重写了接口中的4个方法,并且在无参构造函数中遍历了枚举类型Enabled并对字段enabledMap进行了赋值。

想要使用自定义的类型处理器,也需要在resources/mybatis-config.xml中添加如下配置:

<typeHandlers><!--其他配置--><typeHandler handler="com.zwwhnly.mybatisaction.type.EnabledTypeHandler"javaType="com.zwwhnly.mybatisaction.type.Enabled"/>
</typeHandlers>

运行测试代码,输出日志和上面的输出日志一样,这里不再重复贴出。

mybatis更新时间字段_你以为把Mybatis型处理器了解了,就不会“暴雷”了!相关推荐

  1. mybatis 查询的时间不对_程序员,Mybatis 你踩过坑吗?

    点击上方"Java基基",选择"设为星标" 做积极的人,而不是积极废人! 源码精品专栏 中文详细注释的开源项目 RPC 框架 Dubbo 源码解析 网络应用框架 ...

  2. sql 批量更新时间字段加小时

    sql 批量更新时间字段加小时 update 表名 set 时间字段=时间字段+12/24 where 条件 sql update su_user t set t.update_time = t.up ...

  3. mysql查询今日没有时间字段_关于日期及时间字段的查询

    前言: 在项目开发中,一些业务表字段经常使用日期和时间类型,而且后续还会牵涉到这类字段的查询.关于日期及时间的查询等各类需求也很多,本篇文章简单讲讲日期及时间字段的规范化查询方法. 1.日期和时间类型 ...

  4. 关于状态更新时间字段取值的问题

    create by:关彦明 create time:2016-07-27 --------------------------------------------------------------- ...

  5. java插入或者修改数据自动更新时间字段

    ** 方法一:最简单 ** 在sqlyog界面打开相关的表 在要时间"更新"字段打勾 测试成功 每次修改表中数据 时间字段都会更新 ** 方法二:直接获取当前时间set到数据库 * ...

  6. mysql创建与更新时间字段

    http://blog.sina.com.cn/s/blog_672b419f0101k63f.html DATETIME类型用在你需要同时包含日期和时间信息的值时.MySQL检索并且以'YYYY-M ...

  7. mongodb更新某个字段_直播 | MongoDB开源数据库的云上之路

    本文转自阿里巴巴数据库技术 来了来了!就在今天(11月26号)阿里云-MongoDB战略合作发布会真的来了!一直被模仿从未没超越的开源界大牛MongoDB与亚太区云数据库TOP 1 阿里云数据库要联手 ...

  8. 明日方舟服务器维护时间,明日方舟5月15日版本更新维护延长公告 明日方舟更新时间延长_游侠手游...

    明日方舟5月15日版本更新维护延长公告,明日方舟更新时间延长.明日方舟昨天晚上发出了更新公告表示今天早上8点到12点会进行停机维护.但是现在更新维护又延长了两个小时.不知道官方又在这次的更新中暗藏了一 ...

  9. Mysql设置创建时间字段和更新时间字段自动获取时间,填充时间

    1.引言 在实际开发中,每条数据的创建时间和修改时间,尽量不需要应用程序去记录,而由数据库获取当前时间自动记录创建时间,获取当前时间自动记录修改时间. 2.创建语句 (1)–添加CreateTime ...

最新文章

  1. 深度学习机器学习大牛
  2. Bzoj4212--神牛养成计划
  3. [vue-element]项目中有使用过ElementUI吗?有遇到过哪些问题?它的使用场景主要是哪些?
  4. swoole mysql 连接池_基于Swoole的通用连接池 - 数据库连接池
  5. linux精灵进程之crond
  6. “一加一减”的两种说话技巧
  7. 前端接收pdf文件_原生ajax请求获取pdf文件流本地下载(支持谷歌IE)
  8. mysql show profiles 使用分析sql 性能
  9. 4个小时实现一个HTML5音乐播放器
  10. 惊艳CES!优必选Walker新一代迈出里程碑一步,仿人机器人进入家庭取得重大突破
  11. BZOJ 1260 paint
  12. 江苏大学计算机学院林琳,计算机学院教师岗副高及以下、其它专技中级及以下人员岗位聘用结果公示...
  13. html语言制作带样式的表格,CSS实现的清爽、漂亮的表格样式分享
  14. Unity-黑暗之魂复刻-角色摄相机
  15. 为什么国外服务器域名备案可以不进行?
  16. 微型计算机基础pdf,微型计算机硬件基础.pdf
  17. 为啥现在还有人相信5G辐射危害健康?
  18. 深度学习100例-卷积神经网络(VGG-16)识别海贼王草帽一伙 | 第6天
  19. VS2017生成项目报 找不到资产文件“xxxx\obj\project.assets.json
  20. C++视频会议demo源码下载

热门文章

  1. java bitset_Java BitSet intersects()方法与示例
  2. 为什么HashMap会产生死循环?
  3. 对象复制的7种方法,还是Spring的最好用!
  4. 一文带你看完ZooKeeper!
  5. jenkins用ssh agent插件在pipeline里实现scp和远程执行命令
  6. 百度地图离线sdk java_百度地图SDK java.lang.UnsatisfiedLinkError: Couldn't load BaiduMapSDK...
  7. python.123登录_python用户登录3次
  8. Win10系统java环境配置
  9. 什么意思中文翻译_os常见意思介绍
  10. python语言的数据类型图解_Python基础——数据类型(图解+实例,非常详细!)