在mybatis作为持久层的项目中,如果我们的某个实体类属性有用到枚举类型,那么我们可以通过mybatis的typeHandler来处理,mybatis自带两个处理枚举的typeHandler类:EnumTypeHandler和EnumOrdinalTypeHandler。
先看一种情况:
public enum ResultStatus {
SUCCESS,FAIL,ERROR;
}
如果存放此结果状态值的数据库表设置的是字符varchar类型,那么存入到数据库的值就是SUCCESS、FAIL、ERROR这三种其中的一种。
假若此字段值在表中设置的是int类型,或者你想存入int类型,那么你就要为该枚举指定typeHandler了。由于我们用的是spring boot,所以就如下处理:
@Configuration
@MapperScan("com.bms.mapper")
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor page = new PaginationInterceptor();
page.setDialectType("mysql");
return page;
}
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.getObject().getConfiguration()
.getTypeHandlerRegistry().register(ResultStatus.class, EnumOrdinalTypeHandler.class);
return sqlSessionFactoryBean.getObject();
}
}
这里要注意,我们注册的是EnumOrdinalTypeHandler类。
那么EnumTypeHandler和EnumOrdinalTypeHandler类有什么区别呢?
EnumTypeHandler存入数据库的是枚举的name,EnumOrdinalTypeHandler存入数据库的是枚举的位置,也就是下标,是从0开始的。
其实从EnumTypeHandler和EnumOrdinalTypeHandler的源代码就能看出。
介绍到这里,你或许会说,我不想用下标值来代替,我的枚举定义是这样的,我想存自定义的code:
public enum ResultStatus {
SUCCESS(200,"成功"),FAIL(300,"失败"),ERROR(500,"其他错误");
private Integer code;
private String value;
private ResultStatus(Integer code,String value) {
this.code = code;
this.value = value;
}
public Integer getCode() {
return code;
}
public String getValue() {
return value;
}
public static ResultStatus getResultByCode(Integer code) {
switch (code) {
case 200:
return SUCCESS;
case 300:
return FAIL;
case 500:
return ERROR;
default:
return SUCCESS;
}
}
}
很好,这种情况下,我们就需要自定义typeHandler来处理了。
自定义typeHandler有两种方式:一种是继承BaseTypeHandler类,另一种是实现TypeHandler接口。我们先看第一种:
public class ResultTypeHandler extends BaseTypeHandler<ResultStatus>{
@Override
public void setNonNullParameter(PreparedStatement ps, int i, ResultStatus parameter, JdbcType jdbcType)
throws SQLException {
System.out.println("要保持的code========="+parameter.getCode()+"====="+parameter.getValue());
ps.setString(i, parameter.getCode().toString());
}
@Override
public ResultStatus getNullableResult(ResultSet rs, String columnName) throws SQLException {
int code = rs.getInt(columnName);
System.out.println("从数据库中取出的code============="+code);
ResultStatus resultStatus = ResultStatus.getResultByCode(code);
return resultStatus;
}
@Override
public ResultStatus getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
int code = rs.getInt(columnIndex);
System.out.println("从数据库中取出的code============="+code);
ResultStatus resultStatus = ResultStatus.getResultByCode(code);
return resultStatus;
}
@Override
public ResultStatus getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
int code = cs.getInt(columnIndex);
System.out.println("从数据库中取出的code============="+code);
ResultStatus resultStatus = ResultStatus.getResultByCode(code);
return resultStatus;
}
}
第二种实现方式是:
public class CustomResultTypeHandler implements TypeHandler<ResultStatus>{
/**
* 定义当前数据
*/
@Override
public void setParameter(PreparedStatement ps, int i, ResultStatus parameter, JdbcType jdbcType) throws SQLException {
System.out.println("要保存的code============="+parameter.getCode());
ps.setString(i, parameter.getCode().toString());
}
@Override
public ResultStatus getResult(ResultSet rs, String columnName) throws SQLException {
int code = rs.getInt(columnName);
System.out.println("从数据库中取出的code============="+code);
ResultStatus resultStatus = ResultStatus.getResultByCode(code);
return resultStatus;
}
@Override
public ResultStatus getResult(ResultSet rs, int columnIndex) throws SQLException {
int code = rs.getInt(columnIndex);
System.out.println("从数据库中取出的code============="+code);
ResultStatus resultStatus = ResultStatus.getResultByCode(code);
return resultStatus;
}
@Override
public ResultStatus getResult(CallableStatement cs, int columnIndex) throws SQLException {
int code = cs.getInt(columnIndex);
System.out.println("从数据库中取出的code============="+code);
ResultStatus resultStatus = ResultStatus.getResultByCode(code);
return resultStatus;
}
}
可以看出两种方式很相似,除了要重写的方法名不一样。然后我们就需要注册我们自定义的typeHandler了。
@Configuration
@MapperScan("com.bms.mapper")
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor page = new PaginationInterceptor();
page.setDialectType("mysql");
return page;
}
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.getObject().getConfiguration()
.getTypeHandlerRegistry().register(ResultStatus.class, CustomResultTypeHandler.class);
return sqlSessionFactoryBean.getObject();
}
}
通过以上步骤,我们在存储的时候,就能存储自定义的code了。在获取的时候,也能获取到code,然后通过code获取到整个枚举对象。