mybatis更新时间字段_你以为把Mybatis型处理器了解了,就不会“暴雷”了!
1. 明確需求
在設(shè)計之初,sys_role表的enabled字段有2個可選值,其中0 代表禁用,1代表啟用,而且實體類中我們使用的是Interger類型:
/*** 有效標(biāo)志*/ 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對應(yīng)的索引為0,enabled對應(yīng)的索引為1。
然后將SysRole類中原來為Integer類型的enabled字段修改為:
/*** 有效標(biāo)志*/ 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值"); }雖然上面的代碼很完美的解決了硬編碼的問題,但此時又引出一個新的問題:
數(shù)據(jù)庫并不能識別Enabled枚舉類型,在新增,更新或者作為查詢條件時,需要將枚舉值轉(zhuǎn)換為數(shù)據(jù)庫中的int類型,在查詢數(shù)據(jù)時,需要將數(shù)據(jù)庫的int類型的值轉(zhuǎn)換為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();} }運行測試代碼,發(fā)現(xiàn)拋出如下異常:
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類型和數(shù)據(jù)庫類型時,使用TypeHandler(類型處理器)對這兩者進行轉(zhuǎn)換。
MyBatis為Java類型和數(shù)據(jù)庫JDBC中的常用類型類型提供了TypeHandler接口的實現(xiàn)。
MyBatis在啟動時會加載所有的JDBC對應(yīng)的類型處理器,在處理枚舉類型時默認(rèn)使用org.apache.ibatis.type.EnumTypeHandler處理器,這個處理器會將枚舉類型轉(zhuǎn)換為字符串類型的字面值使用,對于Enabled枚舉來說,就是“disabled"和”enabled"字符串。
而數(shù)據(jù)庫中enabled字段的類型是int,所以在查詢到角色信息將int類型的值1轉(zhuǎn)換為Enabled類型報錯。
那么如何解決這個問題呢?
MyBatis還提供了另一個枚舉處理器:org.apache.ibatis.type.EnumOrdinalTypeHandler,這個處理器使用枚舉的索引進行處理,可以解決此處轉(zhuǎn)換報錯的問題。
使用這個處理器,需要在之前的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轉(zhuǎn)換為了Enabled.enabled,在更新角色信息時,MyBatis將Enabled.disabled轉(zhuǎn)換為了0。
3. 使用自定義的類型處理器
假設(shè)enabled字段的值既不是枚舉的字面值,也不是枚舉的索引值,此時org.apache.ibatis.type.EnumTypeHandler和org.apache.ibatis.type.EnumOrdinalTypeHandler都不能滿足我們的需求,這種情況下我們就需要自己來實現(xiàn)類型處理器了。
首先修改下枚舉類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);} }自定義類型處理器實現(xiàn)了TypeHandler接口,重寫了接口中的4個方法,并且在無參構(gòu)造函數(shù)中遍歷了枚舉類型Enabled并對字段enabledMap進行了賦值。
想要使用自定義的類型處理器,也需要在resources/mybatis-config.xml中添加如下配置:
<typeHandlers><!--其他配置--><typeHandler handler="com.zwwhnly.mybatisaction.type.EnabledTypeHandler"javaType="com.zwwhnly.mybatisaction.type.Enabled"/> </typeHandlers>運行測試代碼,輸出日志和上面的輸出日志一樣,這里不再重復(fù)貼出。
總結(jié)
以上是生活随笔為你收集整理的mybatis更新时间字段_你以为把Mybatis型处理器了解了,就不会“暴雷”了!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android Studio Gradl
- 下一篇: 排序算法 —— 计数排序