java 枚举 程序数据库实际项目使用

枚举相对来说,是很常见的一种使用类型,但是在实际项目中,使用更加广泛,在很多场景,页面使用的是汉字,而数据库存储的却是数字,java程序运行时传输的便是枚举,这就涉及到了数据的展示,传输,存储

示例:项目使用的是微服务(spring could),单体子应用为spring boot + mybatis ,数据库使用mysql

①.页面给用户展示的时候,自然是汉字,也就是描述,如图

②.java程序所接收与传输的类型便是枚举,如图(注:@ApiModelProperty注解为项目中使用springfox-swagger2,与本文介绍无关)

③.枚举类,如图

④.数据库字段类型为TINYINT,如图

以上①②③④已介绍各个环节的示例图,在我们java程序中使用的是OrgTypeEnum枚举类型作为传输类型,在页面,给用户展示的是枚举中的description字段值,而我的数据库中存储的是枚举类中的code字段值,这就牵扯到类型转换

实际开发过程:

一:页面JS发起的ajax请求枚举字段值直接使用枚举值(大写字母),例如:机构类型为总公司,则字段传输时直接赋值为 {"orgType": "HEADQUARTERS"} 

二:java程序Controller层用实体对象接收,注意@RequestBody注解别忘了写,如图所示

三:该项目为mysql与mybatis,故涉及到mybatis转换器,(转换器显现原理在此文章中先不介绍,请自行查阅资料)

四:XML文件中,如果涉及到枚举类型的表单XML,则无法使用自动驼峰命名法,需要设置resultMap值,在基本的String或者int,long之类的类型可以不用写jdbcType,但是枚举字段,必须要写typeHandler,必须制定typeHandler为自己提供的转换器,例如:typeHandler="*.*.*.*.mybatis.handler.EnumTypeHandler" (此路径为转换器类路径)

五:页面需要知道枚举值是什么,则需要传输给页面,在项目公有返回实体中添加一个字段代表枚举值,如图

六:页面接口相应,如图

以上,则是实际项目中,枚举应用场景之一的介绍,下面贴出所有相应代码片段

BaseEnum

public interface BaseEnum {
    Integer getCode();

    String getDescription();
}

EnumTypeHandler

public class EnumTypeHandler extends BaseTypeHandler<BaseEnum> {

    private Class<BaseEnum> type;

    private final BaseEnum[] enums;

    /**
     * 设置配置文件设置的转换类以及枚举类内容,供其他方法更便捷高效的实现
     * @param type 配置文件中设置的转换类
     */
    public EnumTypeHandler(Class<BaseEnum> type) {
        if (type == null)
            throw new IllegalArgumentException("Type argument cannot be null");
        this.type = type;
        this.enums = type.getEnumConstants();
    }

    @Override
    public BaseEnum getNullableResult(ResultSet rs, String columnName) throws SQLException {
        // 根据数据库存储类型决定获取类型,本例子中数据库中存放INT类型
        int i = rs.getInt(columnName);
        if (rs.wasNull()) {
            return null;
        } else {
            // 根据数据库中的code值,定位BaseEnum子类
            return locateBaseEnum(i);
        }
    }

    @Override
    public BaseEnum getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        // 根据数据库存储类型决定获取类型,本例子中数据库中存放INT类型
        int i = rs.getInt(columnIndex);
        if (rs.wasNull()) {
            return null;
        } else {
            // 根据数据库中的code值,定位BaseEnum子类
            return locateBaseEnum(i);
        }
    }

    @Override
    public BaseEnum getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        // 根据数据库存储类型决定获取类型,本例子中数据库中存放INT类型
        int i = cs.getInt(columnIndex);
        if (cs.wasNull()) {
            return null;
        } else {
            // 根据数据库中的code值,定位BaseEnum子类
            return locateBaseEnum(i);
        }
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, BaseEnum parameter, JdbcType jdbcType)
            throws SQLException {
        // baseTypeHandler已经帮我们做了parameter的null判断
        ps.setInt(i, parameter.getCode());
    }

    /**
     * 枚举类型转换,由于构造函数获取了枚举的子类enums,让遍历更加高效快捷
     * @param code 数据库中存储的自定义code属性
     * @return code对应的枚举类
     */
    private BaseEnum locateBaseEnum(int code) {
        for (BaseEnum status : enums) {
            if (status.getCode().equals(Integer.valueOf(code))) {
                return status;
            }
        }
        throw new IllegalArgumentException("未知的枚举类型:" + code + ",请核对" + type.getSimpleName());
    }

}

EnumUtil

public class EnumUtil {

    /**默认枚举类属性*/
    private final static String[] ATTRIBUTE_NAME_ARR = {"code", "description"};

    /**
     * Description: [将Enum枚举转换成JSON字符串]
     * @param clazz 枚举class
     * @param attributeNames 枚举属性,可不填,默认枚举属性为[code,description]
     * @return: java.lang.String 处理后的JSON字符串
     * @version 1.0
     **/
    public static String getEnumJson(Class clazz, String ... attributeNames) {
        if (!clazz.isEnum()) {
            return null;
        }
        try {
            String[] attributeNameArr = (attributeNames != null && attributeNames.length > 0) ? attributeNames : ATTRIBUTE_NAME_ARR;
            StringBuilder jsonBud = new StringBuilder();
            jsonBud.append("[");
            List enumList = Arrays.asList(clazz.getEnumConstants());
            int size = enumList.size();
            for (int i = 0; i < size; i ++) {
                jsonBud.append("{");
                Object enumObj = enumList.get(i);
                jsonBud.append("\"").append("enumValue").append("\":").append("\"").append(enumObj).append("\",");
                int length = attributeNameArr.length;
                for (int j = 0; j < length; j ++) {
                    String attributeName = attributeNameArr[j];
                    String getMethodName = "get" + caseInitials(attributeName);
                    Method method = clazz.getMethod(getMethodName);
                    boolean flag = "class java.lang.String".equals(method.getReturnType().toString());
                    Object obj = method.invoke(enumObj);
                    jsonBud.append("\"").append(attributeName).append("\":");
                    if (flag) {
                        jsonBud.append("\"").append(obj).append("\"");
                    } else {
                        jsonBud.append(obj);
                    }
                    if (j < length - 1) {
                        jsonBud.append(",");
                    }
                }
                jsonBud.append("}");
                if (i < size - 1) {
                    jsonBud.append(",");
                }
            }
            jsonBud.append("]");
            return jsonBud.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Description: [首字母大写]
     * @param attribute 目标字符串
     * @return: java.lang.String
     * @version 1.0
     **/
    private static String caseInitials(String attribute){
        if (null == attribute) {
            return null;
        }
        char[] cs = attribute.toCharArray();
        cs[0] -= 32;
        return String.valueOf(cs);
    }

}

注:使用EnumUtil时,请注意枚举类的属性名,如果有变更,则请修改EnumUtil中的ATTRIBUTE_NAME_ARR属性值!

©转载请标明出处,若有疑问,请联系:1982580674@qq.com

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值