1.场景
日常java开发中经常有这种需求,用0或者1这些代码(不局限于数字)来表示某种状态。比如用0表示女性,用1来表示男性。而且写入数据库可能是一个标识,从数据库读取又还原为具体的说明。而且一般情况下为了更好理解或者消除魔法值,通常的处理方案是定义一个枚举:
有些枚举是这样定义的
public enum GenderType{
FEMALE,MALE,UNKNOWN
}
那么通常很多人会这么入库(java伪代码)
if(GenderType.MALE){
// 写入 1
}else if(GenderType.FEMALE){
// 写入 0
}else{
//也可能是泰国回来的 那就 2
}
读取的时候要么同样按照上面的再反向处理一次或者使用数据库sql语法case when
来直接写入DTO
CASE gender
WHEN 1 THEN '男'
WHEN 0 THEN '女'
ELSE '未知' END
这种处理方式看起来不是很优雅。而且多了很多的判断和处理逻辑,和我们的业务并不是非常相关。所以我们可以选择更好的处理方式。
2.Mybatis中的TypeHandler
如果你ORM框架用的是Mybatis。那么将很容易通过TypeHandler<T>接口解决这个问题。
2.1 TypeHandler 分析
public interface TypeHandler<T> {
void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
T getResult(ResultSet rs, String columnName) throws SQLException;
T getResult(ResultSet rs, int columnIndex) throws SQLException;
T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}
源码分析:
- setParameter 方法 通过 传入的T类型写你自己的逻辑,选择调用 PreparedStatement 对象的某个set方法将数据写入数据库。此方法用来写库。
- getResult(ResultSet rs, String columnName) 通过字段名来读库并转换为T类型。
- getResult(ResultSet rs, int columnIndex) 通过字段索引来读库并转换为T类型。
- getResult(CallableStatement cs, int columnIndex) 调用存储过程来获取结果并转换为T类型。
2.2 EnumOrdinalTypeHandler
我们发现TypeHandler有一个实现类EnumOrdinalTypeHandler。字