TypeHandler
处理数据库类型和Java类型之间的转换。
在远古时期我们学习过jdbc, 那时候读取数据库需要手写从ResultSet通过columnName或者columnIndex读取数据。现在用上框架了也不要忘记老本行,mybatis底层同样是这么干的,我们看一下源码。抽象类BaseTypeHandler
实现的TypeHandler
的getResult方法。
@Override
public T getResult(ResultSet rs, String columnName) throws SQLException {
try {
return getNullableResult(rs, columnName);
} catch (Exception e) {
throw new ResultMapException("Error attempting to get column '" + columnName + "' from result set. Cause: " + e, e);
}
}
其中getNullableResult(rs, columnName);
就是读取数据,是不是很熟悉,点进去看一下他是怎么写的。
public abstract T getNullableResult(ResultSet rs, String columnName) throws SQLException;
这是个抽象方法,这个BaseTypeHandler
就是给具体的类型转换器集成的,这样子类只需要实现getNullableResult
方法就能只写getResult
具体处理过程,不需要处理异常。类似于模板方法设计模式,这是种将具体操作延迟到子类的做法。我们随意挑选一个Mybatis的类型转换器BigIntegerTypeHandler
看一下他是怎么实现的(其他代码没粘贴出来,点代码打开点进去看看 非常简单)。
@Override
public BigInteger getNullableResult(ResultSet rs, String columnName) throws SQLException {
BigDecimal bigDecimal = rs.getBigDecimal(columnName);
return bigDecimal == null ? null : bigDecimal.toBigInteger();
}
直接使用了ResultSet::getBigDecimal
,这个例子虽然不太直观但简单粗暴的看到了类型转换器的具体实现。当你觉得mybatis提供的这些转换器不够用时,我们可以自己自定义一个类型转换器,最终在你的mapper.xml中指定,就可以完成类型转换了。实操一下。
简单的假设你现在实体类中有一个枚举类型想要自动转换,我们自定义一个枚举转换器。同样是一个不恰当的例子但能演示功能。
枚举类GenderEnum
@Getter
@AllArgsConstructor
@ToString
public enum GenderEnum {
MALE("1", "男"),
FEMALE("2", "女"),
;
private final String code;
private final String desc;
}
实体类User.java
@TableName("user")
@Slf4j
@Getter
@Setter
public class User implements Serializable {
@TableId
String id;
@TableField("username")
String username;
@TableField("pswd")
String pswd;
@TableField("gender")
GenderEnum gender;
}
自定义类型转换器GenderEnumTypeHandler
public class GenderEnumTypeHandler extends BaseTypeHandler<GenderEnum> {
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int i, GenderEnum genderEnum, JdbcType jdbcType) throws SQLException {
preparedStatement.setString(i, genderEnum.getCode());
}
@Override
public GenderEnum getNullableResult(ResultSet resultSet, String columName) throws SQLException {
String code = resultSet.getString(columName);
return GenderEnum.parseGenderByCode(code);
}
@Override
public GenderEnum getNullableResult(ResultSet resultSet, int index) throws SQLException {
String code = resultSet.getString(index);
return GenderEnum.parseGenderByCode(code);
}
@Override
public GenderEnum getNullableResult(CallableStatement callableStatement, int index) throws SQLException {
String code = callableStatement.getString(index);
return GenderEnum.parseGenderByCode(code);
}
}
UserMapper.xml
,在resultMap中对性别枚举指定typeHandler为自己写的类型转换器。
运行看看类型转换成功了没
好了,关于typeHandler的分享就到这里了,代码写的很简陋,实际会封装的复杂一点。