美文网首页
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封装和数据库类型自动转换

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