BaseEnums封装和数据库类型自动转换
2020-08-12 本文已影响0人
prope
- 需求背景
对项目中的枚举和数据库表中自动转换映射。(存放枚举转换为int,读取int转换为枚举) - 说明: 在开发一些管理系统的时候会返回一个字段多个值的情况,而且这个字段还有对应的 编码和中文名。一方面我们数据库一般存储的是编码 但是页面显示又需要显示编码对应的中文,为了解决这个问题我们找到了解决方案。
- 实现步骤
1:编写接口BaseEnums
/**
* 枚举类的统一处理
* @author wanter
*
* @param <T> 自己的类型
*/
public interface BaseEnums<T> {
/**
* 获取编码
*
* @return
*/
Integer getCode();
/**
* 获取名称
*
* @return
*/
String getName();
}
2:编写EnumUtil工具库类
/**
* 枚举处理工具类
*
* @author xxx
* @date 2020年08月12日18:19:23
*/
public class EnumUtil {
/**
* 根据code获取枚举
*
* @param enumClass
* @param code
* @param <E>
* @return
*/
public static <E extends Enum<?> & BaseEnums> E codeOf(Class<E> enumClass, int code) {
E[] enumConstants = enumClass.getEnumConstants();
for (E e : enumConstants) {
if (e.getCode() == code) {
return e;
}
}
return null;
}
/**
* 根据msg获取枚举
*
* @param enumClass
* @param name
* @param <E>
* @return
*/
public static <E extends Enum<?> & BaseEnums> E nameOf(Class<E> enumClass, String name) {
E[] enumConstants = enumClass.getEnumConstants();
for (E e : enumConstants) {
if (e.getName().equals(name)) {
return e;
}
}
return null;
}
}
3:编写mybatis的类型处理器(mybatis如何转换BaseEnums类型数据)
/**
* 对枚举和数据库表之间的翻译
*
* @author xxx
* @date 2020年08月12日18:22:28
*/
public class CommonEnumsHandler<E extends Enum<?> & BaseEnums> extends BaseTypeHandler<BaseEnums> {
private Class<E> type;
public CommonEnumsHandler(Class<E> type) {
if (type == null) {
throw new IllegalArgumentException("Type argument cannot be null");
}
this.type = type;
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, BaseEnums parameter, JdbcType jdbcType) throws SQLException {
ps.setInt(i, parameter.getCode());
}
@Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
int i = rs.getInt(columnName);
if (rs.wasNull()) {
return null;
} else {
return locateEnumStatus(i);
}
}
@Override
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
int i = rs.getInt(columnIndex);
if (rs.wasNull()) {
return null;
} else {
return locateEnumStatus(i);
}
}
@Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
int i = cs.getInt(columnIndex);
if (cs.wasNull()) {
return null;
} else {
return locateEnumStatus(i);
}
}
/**
* 枚举类型转换,由于构造函数获取了枚举的子类enums,让遍历更加高效快捷
*
* @param code 数据库中存储的自定义code属性
* @return code对应的枚举类
*/
private E locateEnumStatus(Integer code) {
return EnumUtil.codeOf(type, code);
}
- 编写枚举
1:系统正常枚举,实现接口BaseEnums
/**
* <p>
* 设置数据是否有效
*
* @author xxx
* @version 1.0
* @since 2019年10月12日17:39:32
*/
public enum DeleteEnum implements BaseEnums<DeleteEnum> {
// 删除
DELETE_YES(0, "无效"),
//不删除
DELETE_NO(1, "有效");
private Integer code;
private String name;
DeleteEnum(Integer code, String name) {
this.code = code;
this.name = name;
}
@Override
public Integer getCode() {
return code;
}
@Override
public String getName() {
return name;
}
}
2:在其他实体类中使用该字段
/**
* @author xxx
* @version 1.0
* @since 2020年08月12日18:32:39
*/
public class CapitalDebt extends BaseEntity<CapitalDebt> {
private Long id;
private String uuid;
/**
* 是否删除 0=删除 1=有效
*/
private DeleteEnum deleteFlag;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public DeleteEnum getDeleteFlag() {
return deleteFlag;
}
public void setDeleteFlag(DeleteEnum deleteFlag) {
this.deleteFlag = deleteFlag;
}
@Override
public String toString() {
return "CapitalDebt{" +
"id=" + id +
", uuid='" + uuid + '\'' +
", deleteFlag=" + deleteFlag +
'}';
}
}
3:编写xml
<!-- resultMap 中的定义 -->
<resultMap type="com.xxx.xxxx" id="xxxMap">
<result property="id" column="ID"/>
<result property="uuid" column="UUID"/>
<result property="deleteFlag" column="delete_flag" typeHandler="com.xxx.CommonEnumsHandler"/>
</resultMap>
<!-- 取出实体类中值处理 -->
<sql id="entity_properties">
#{id},
#{uuid},
#{deleteFlag ,typeHandler=com.xxx.CommonEnumsHandler}
</sql>
4:升级使用
如果在系统中所有的枚举BaseEnums的情况下,如果每个xml都这么编写,则维护成本太高,有没有什么办法让mybatis知道凡是遇到BaseEnums这种类型都调用CommonEnumsHandler这个处理器来处理这个类型。答案是可以的吗?
所以只需要“告诉”mybatis,讲BaseEnums和CommonEnumsHandler全局绑定起来就可以。
**
* 设置xml文件的扫描位置和
* mapper对应的接口的扫描位置
*
* @author xxx
* @version 2020年08月12日18:49:18
*/
@Configuration
@MapperScan({"com.*.*.*.mapper"})
public class MyBatisConfig {
@Resource
private DataSource dataSource;
private final static String MAPPER_LOCATION = "classpath:/mapper/**.xml";
/**
* 设置xml扫描的位置
* 设置开启驼峰转大写的开关
*
* @return SqlSessionFactory
* @throws Exception
*/
@Bean
public SqlSessionFactory sqlSessionFactoryBean() throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
//自动使用驼峰命名属性映射字段
configuration.setMapUnderscoreToCamelCase(true);
// configuration.setDefaultEnumTypeHandler(CommonEnumsHandler.class);
//讲typeHander 默认注入到mybatis中
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
typeHandlerRegistry.register(BaseEnums.class, CommonEnumsHandler.class);
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sqlSessionFactoryBean.setMapperLocations(resolver.getResources(MAPPER_LOCATION));
sqlSessionFactoryBean.setConfiguration(configuration);
return sqlSessionFactoryBean.getObject();
}
}
其中代码在项目启动的时候自动带入到全局解析中
typeHandlerRegistry.register(BaseEnums.class, CommonEnumsHandler.class);
本文完
- 关键词
Enum类型,mybatis类型映射,spring boot枚举优雅处理。typeHandler处理枚举