文章目录
- 使用MyBatis提供的枚举处理器
- 使用自定义的类型处理器
使用MyBatis提供的枚举处理器
sys_role 表中有一个字段 enabled,这个字段只有 1 和 0 两个可选值。在 SysRole 类中,使用 Integer enabled,这种情况下必须手动校验 enabled 的值。使用枚举可以更加轻松的进行校验。
新增 Enabled 枚举类:
public enum Enabled {
disabled,//禁用
enabled;//启用
}
枚举除了本身的字面值外,还可以通过枚举的 ordinal() 方法获取枚举值的索引。在这个枚举类中,disabled 对应索引 0,enabled 对应索引 1。
将 SysRole 中 enabled 类型修改为 enum:
public class SysRole {
// 其它属性
private Enabled enabled;
// 其它getter和setter方法
public Enabled getEnabled() {
return enabled;
}
public void setEnabled(Enabled enabled) {
this.enabled = enabled;
}
}
在数据库中 enabled 字段的类型是 int,因此在和数据库进行交互的时候,不能直接使用枚举类型,需要将枚举值转换为数据库中的 int 类型。
MyBatis 在处理 Java 类型和数据库类型时,使用 TypeHandler(类型处理器)对这两者进行转换。MyBatis 为 java 和 数据库 JDBC 中的基本类型和常用的类型提供了 TypeHandler 接口的实现。
MyBatis 在启动时会加载所有的 JDBC 对应的类型处理器,在处理枚举类型时默认使用 org.apache.ibatis.type.EnumTypeHandler 处理器,这个处理器会将枚举类型转换为字符串类型的字面值并使用,对于 Enabled 而言便是 “disabled” 和 “enabled” 字符串。
除此之外,MyBatis 还提供了另外一个 org.apache.ibatis.type.EnumOrdinalTypeHandler 处理器,这个处理器使用枚举的索引进行处理,对于 Enabled 而言便是 0(disabled) 和 1(enabled) 。想使用这个处理器需要在 mybatis-config.xml 中添加如下配置:
<typeHandlers>
<typeHandler
javaType="tk.mybatis.simple.type.Enabled"
handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/>
</typeHandlers>
javaType 为要处理的类型,handler 为要使用的类型处理器。
测试方法:
@Test
public void testUpdateById() {
SqlSession sqlSession = getSqlSession();
try {
RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
//先查询出角色
SysRole role = roleMapper.selectById(2L);
//数据库中这个角色的enabled字段值为1,对应启用状态
Assert.assertEquals(Enabled.enabled, role.getEnabled());
//修改角色的enabled值为disabled,禁用状态
role.setEnabled(Enabled.disabled);
//执行更新
roleMapper.updateById(role);
} finally {
// TODO: handle finally clause
sqlSession.rollback();
sqlSession.close();
}
}
控制台输出:
DEBUG [main] - ==> Preparing: select id, role_name roleName, enabled, create_time 'createInfo.createTime', create_by 'createInfo.createBy' from sys_role where id = ?
DEBUG [main] - ==> Parameters: 2(Long)
TRACE [main] - <== Columns: id, roleName, enabled, createInfo.createTime, createInfo.createBy
TRACE [main] - <== Row: 2, 普通用户, 1, 2019-01-06 10:36:27.0, 1
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-01-06 10:36:27.0(Timestamp), 2(Long)
DEBUG [main] - <== Updates: 1
第7行可以看出,MyBatis 已将 Enabled 的 disabled 值转换为 0(Integer)。
使用自定义的类型处理器
如果数据库存储的字段值既不是枚举的字面值,也不是枚举的索引值,这种情况就需要自己来实现类型处理器了。
修改枚举类 Enabled :
package tk.mybatis.simple.type;
public enum Enabled {
enabled(1),
disabled(0);
private final int value;
private Enabled(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
新增一个 EnabledTypeHandler 类,实现 TypeHandler 接口,泛型为 Enabled:
package tk.mybatis.simple.type;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
public class EnabledTypeHandler implements TypeHandler<Enabled> {
private final Map<Integer, Enabled> enabledMap = new HashMap<Integer, Enabled>();
public EnabledTypeHandler() {
// TODO Auto-generated constructor stub
//这里将Enabled枚举类中的枚举类型放入Map中,以它们的枚举值作为key
for(Enabled enabled : Enabled.values()) {
enabledMap.put(enabled.getValue(), enabled);
}
}
/*
* 定义当前数据如何保存到数据库中
* @see org.apache.ibatis.type.TypeHandler#setParameter(java.sql.PreparedStatement, int, java.lang.Object, org.apache.ibatis.type.JdbcType)
*/
@Override
public void setParameter(PreparedStatement ps, int i, Enabled parameter, JdbcType jdbcType) throws SQLException {
// TODO Auto-generated method stub
ps.setInt(i, parameter.getValue());
}
/*
* 从数据库中获取value
* @see org.apache.ibatis.type.TypeHandler#getResult(java.sql.ResultSet, java.lang.String)
*/
@Override
public Enabled getResult(ResultSet rs, String columnName) throws SQLException {
// TODO Auto-generated method stub
Integer value = rs.getInt(columnName);
return enabledMap.get(value);
}
@Override
public Enabled getResult(ResultSet rs, int columnIndex) throws SQLException {
// TODO Auto-generated method stub
Integer value = rs.getInt(columnIndex);
return enabledMap.get(value);
}
/*
* 处理存储过程结果集
* @see org.apache.ibatis.type.TypeHandler#getResult(java.sql.CallableStatement, int)
*/
@Override
public Enabled getResult(CallableStatement cs, int columnIndex) throws SQLException {
// TODO Auto-generated method stub
Integer value = cs.getInt(columnIndex);
return enabledMap.get(value);
}
}
我将 Enabled 枚举类中的枚举类型放入了 Map 中,以它们的枚举值作为 key。也可以在 Enabled 类中写一个 getEnabledByValue 静态方法,通过枚举值取出枚举类型。
实现了 TypeHandler 接口的 4 个方法,第 1 个方法是写入数据库用的,后面 3 个方法作用都是从数据库返回的结果中,拿值进行转换。
写好类型处理器后,还需要在 mybatis-config.xml 中进行配置:
<typeHandlers>
<typeHandler
javaType="tk.mybatis.simple.type.Enabled"
handler="tk.mybatis.simple.type.EnabledTypeHandler"/>
</typeHandlers>