# 明確需求在設(shè)計(jì)之初,sys_role表的enabled字段有2個(gè)可選值,其中0 代表禁用,1代表啟用,而且實(shí)體類中我們使用的是Interger類型:/*** 有效標(biāo)志*/private Integer enabled;public Integer getEnabled(...
在設(shè)計(jì)之初,sys_role表的enabled字段有2個(gè)可選值,其中0 代表禁用,1代表啟用,而且實(shí)體類中我們使用的是Interger類型:
/**
* 有效標(biāo)志
*/
private Integer enabled;
public Integer getEnabled() {
return enabled;
}
public void setEnabled(Integer enabled) {
this.enabled = enabled;
}
如果要新增或者更新角色信息,我們肯定要校驗(yàn)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值");
}
這種硬編碼的方式不僅看起來不友好,而且不利于后期維護(hù),如果維護(hù)的程序員脾氣不好,還會(huì)罵你,哈哈。
所以我們的需求就是,拒絕硬編碼,使用友好的編碼方式來校驗(yàn)enabled字段的值是否有效。
# 使用MyBatis提供的枚舉類型處理器
我們通常會(huì)使用枚舉來解決這種場(chǎng)景。
首先新建com.zwwhnly.mybatisaction.type包,然后在該包下新建枚舉Enabled:
package com.zwwhnly.mybatisaction.type;
public enum Enabled {
/**
* 禁用
*/
disabled,
/**
* 啟用
*/
enabled;
}
其中,disabled對(duì)應(yīng)的索引為0,enabled對(duì)應(yīng)的索引為1。
然后將SysRole類中原來為Integer類型的enabled字段修改為:
/**
* 有效標(biāo)志
*/
private Enabled enabled;
public Enabled getEnabled() {
return enabled;
}
public void setEnabled(Enabled enabled) {
this.enabled = enabled;
}
此時(shí)原本硬編碼的代碼就可以修改為:
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í)又引出一個(gè)新的問題:
數(shù)據(jù)庫并不能識(shí)別Enabled枚舉類型,在新增,更新或者作為查詢條件時(shí),需要將枚舉值轉(zhuǎn)換為數(shù)據(jù)庫中的int類型,在查詢數(shù)據(jù)時(shí),需要將數(shù)據(jù)庫的int類型的值轉(zhuǎn)換為Enabled枚舉類型。
帶著這個(gè)問題,我們?cè)赟ysRoleMapperTest測(cè)試類中添加如下測(cè)試方法:
@Test
public void testUpdateById() {
SqlSession sqlSession = getSqlSession();
try {
SysRoleMapper sysRoleMapper = sqlSession.getMapper(SysRoleMapper.class);
// 先查詢出id=2的角色,然后修改角色的enabled值為disabled
SysRole sysRole = sysRoleMapper.selectById(2L);
Assert.assertEquals(Enabled.enabled, sysRole.getEnabled());
// 修改角色的enabled為disabled
sysRole.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();
}
}
運(yùn)行測(cè)試代碼,發(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
這是因?yàn)镸yBatis在處理Java類型和數(shù)據(jù)庫類型時(shí),使用TypeHandler(類型處理器)對(duì)這兩者進(jìn)行轉(zhuǎn)換。
MyBatis為Java類型和數(shù)據(jù)庫JDBC中的常用類型類型提供了TypeHandler接口的實(shí)現(xiàn)。
MyBatis在啟動(dòng)時(shí)會(huì)加載所有的JDBC對(duì)應(yīng)的類型處理器,在處理枚舉類型時(shí)默認(rèn)使用org.apache.ibatis.type.EnumTypeHandler處理器,這個(gè)處理器會(huì)將枚舉類型轉(zhuǎn)換為字符串類型的字面值使用,對(duì)于Enabled枚舉來說,就是“disabled"和”enabled"字符串。
而數(shù)據(jù)庫中enabled字段的類型是int,所以在查詢到角色信息將int類型的值1轉(zhuǎn)換為Enabled類型報(bào)錯(cuò)。
那么如何解決這個(gè)問題呢?
MyBatis還提供了另一個(gè)枚舉處理器:org.apache.ibatis.type.EnumOrdinalTypeHandler,這個(gè)處理器使用枚舉的索引進(jìn)行處理,可以解決此處轉(zhuǎn)換報(bào)錯(cuò)的問題。
使用這個(gè)處理器,需要在之前的resources/mybatis-config.xml中添加如下配置:
<typeHandlers>
<typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"
javaType="com.zwwhnly.mybatisaction.type.Enabled"/>
</typeHandlers>
再次運(yùn)行測(cè)試代碼,測(cè)試通過,輸出日志如下:
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_time
TRACE [main] - <== Row: 2, 普通用戶, 1, 1, 2019-06-27 18:21:12.0
DEBUG [main] - <== Total: 1
DEBUG [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
從日志中可以看出,在查詢角色信息時(shí),MyBatis將1轉(zhuǎn)換為了Enabled.enabled,在更新角色信息時(shí),MyBatis將Enabled.disabled轉(zhuǎn)換為了0。
# 使用自定義的類型處理器
假設(shè)enabled字段的值既不是枚舉的字面值,也不是枚舉的索引值,此時(shí)org.apache.ibatis.type.EnumTypeHandler和org.apache.ibatis.type.EnumOrdinalTypeHandler都不能滿足我們的需求,這種情況下我們就需要自己來實(shí)現(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);
}
}
@Override
public void setParameter(PreparedStatement preparedStatement, int i, Enabled enabled, JdbcType jdbcType) throws SQLException {
preparedStatement.setInt(i, enabled.getValue());
}
@Override
public Enabled getResult(ResultSet resultSet, String s) throws SQLException {
Integer value = resultSet.getInt(s);
return enabledMap.get(value);
}
@Override
public Enabled getResult(ResultSet resultSet, int i) throws SQLException {
Integer value = resultSet.getInt(i);
return enabledMap.get(value);
}
@Override
public Enabled getResult(CallableStatement callableStatement, int i) throws SQLException {
Integer value = callableStatement.getInt(i);
return enabledMap.get(value);
}
}
自定義類型處理器實(shí)現(xiàn)了TypeHandler接口,重寫了接口中的4個(gè)方法,并且在無參構(gòu)造函數(shù)中遍歷了枚舉類型Enabled并對(duì)字段enabledMap進(jìn)行了賦值。
想要使用自定義的類型處理器,也需要在resources/mybatis-config.xml中添加如下配置:
<typeHandlers>
<!--其他配置-->
<typeHandler handler="com.zwwhnly.mybatisaction.type.EnabledTypeHandler"
javaType="com.zwwhnly.mybatisaction.type.Enabled"/>
</typeHandlers>
運(yùn)行測(cè)試代碼,輸出日志和上面的輸出日志一樣,這里不再重復(fù)貼出。
來源:本文內(nèi)容搜集或轉(zhuǎn)自各大網(wǎng)絡(luò)平臺(tái),并已注明來源、出處,如果轉(zhuǎn)載侵犯您的版權(quán)或非授權(quán)發(fā)布,請(qǐng)聯(lián)系小編,我們會(huì)及時(shí)審核處理。
聲明:江蘇教育黃頁對(duì)文中觀點(diǎn)保持中立,對(duì)所包含內(nèi)容的準(zhǔn)確性、可靠性或者完整性不提供任何明示或暗示的保證,不對(duì)文章觀點(diǎn)負(fù)責(zé),僅作分享之用,文章版權(quán)及插圖屬于原作者。
Copyright?2013-2024 JSedu114 All Rights Reserved. 江蘇教育信息綜合發(fā)布查詢平臺(tái)保留所有權(quán)利
蘇公網(wǎng)安備32010402000125
蘇ICP備14051488號(hào)-3技術(shù)支持:南京博盛藍(lán)睿網(wǎng)絡(luò)科技有限公司
南京思必達(dá)教育科技有限公司版權(quán)所有 百度統(tǒng)計(jì)