美文网首页
BaseEnums封装和数据库类型自动转换

BaseEnums封装和数据库类型自动转换

作者: prope | 来源:发表于2020-08-12 18:59 被阅读0次
  • 需求背景
    对项目中的枚举和数据库表中自动转换映射。(存放枚举转换为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内置了很多处理器来帮我们处理常见的数据类型,比如 BaseTypeHandler的实现类
所以只需要“告诉”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处理枚举

相关文章

  • BaseEnums封装和数据库类型自动转换

    需求背景对项目中的枚举和数据库表中自动转换映射。(存放枚举转换为int,读取int转换为枚举) 说明: 在开发一些...

  • 四、SQL函数④(其他函数)

    类型转换 隐式转换:数据库系统自动将字符串类型转换为整数类型显式转换:使用类型转换函数转换。使用类型转换函数不仅可...

  • java数据类型

    1、整型拓展 2、浮点数 3、类型转换 java强制类型转换和自动类型转换。自动类型转换是程序执行过程中自动进行转...

  • Java 数据类型的自动转换和强制转换

    Java 数据类型的自动转换和强制转换 自动转换 自动转换适用于低位数类型向高位数类型的转换 规则: 对于算术运算...

  • Java 学习笔记_2

    1、隐式转换 和 强制类型转换 隐式转换: 又叫自动类型转换。由系统自动完成的类型转换. 从存储范围小的类型到存储...

  • JAVA数据类型转换

    普通类型自动转换 左边的数据类型可以自动转换到右边的数据类型 String类型自动转换 普通基本类型可以自动转换为...

  • 2、强制数据类型转换

    数据类型转换: 在js中,数据类型的转换有两种,分别是自动转换和强制转换 自动转换: 自动转换是用JS进行某些操作...

  • 第十一章 使用类(4)类的自动转换和强制类型转换

    (四)类的自动转换和强制类型转换 1.对内置基本数据类型的转换: C++如何处理数据类型的转换,包括自动转换和强...

  • Java 语言如何实现数据自动化类型转换

    数据类型的转换分为两种 : 1.自动类型转换2.被动类型转换 我们首先来解析自动类型转换 自动类型转换 我们讲解了...

  • day04-python中的循环与分支结构

    01-数据类型转换 1、数据类型的自动转换(主要是整型和浮点型之间自动转换) 2、数据类型的强制转换格式:类型名(...

网友评论

      本文标题:BaseEnums封装和数据库类型自动转换

      本文链接:https://www.haomeiwen.com/subject/hhumdktx.html