在系统中,有些类型、状态等特别多,代码中写了很多的逻辑判断。本文将枚举类和普通java数据类型的字段一样在mybatise中直接操作存入修改和查询返回,并且以整个项目考虑,适用于项目中存在大量的枚举类情形,不要觉得复杂内容长,不就是粘贴复制吗?超级简单好吧!如下xml中是对一个表的基本操作:
下面是含有枚举类属性的普通java类
public class ContractSignatureEntity extends BaseEntity { /** * 电子合同模板配置ID */ private Integer contractTemplateId; /** * 电子合同签署状态 */ private SignatureStatus signatureStatus;
get。。set..
}
一个普通的枚举类
public enum SignatureStatus implements EnumShow { SIGN_CANCEL(-1, "已撤销", "已撤销"), SIGN_ARCHIVED_FAILED(-7, "签署中", "归档失败"), SIGN_ARCHIVED_SUCCESS(7, "已归档", "已归档"); private int value; private String desc; private String flowDesc; SignatureStatus(int value, String desc, String flowDesc) { this.value = value; this.desc = desc; this.flowDesc = flowDesc; } public static SignatureStatus forValue(int value) { for (SignatureStatus signatureStatus : SignatureStatus.values()) { if (signatureStatus.value == value) { return signatureStatus; } } return null; } /** * 生成合同状态位 * * @return */ public static ListgetCanGenerateStatus() { return Arrays.asList(INIT, SIGN_CANCEL); } /** * 落公司章状态位 * * @return */ public static List getCanCompanySignStatus() { return Arrays.asList(SIGN_PROCESSED_USER_SUCCESS, SIGN_PROCESSED_COM_FAILED); } @Override public String getName() { return name(); } @Override public int getValue() { return value; } @Override public String getDesc() { return desc; } public String getFlowDesc() { return flowDesc; } }
EnumShow 提供给前端用的枚举名称,重写了枚举getName,如果前端不需要可以直接实现EnumBehaviour接口
public interface EnumShow extends EnumBehaviour { String getName(); }
我们有两个枚举类需要实现的接口,EnumBehaviour(int类型)和EnumStringBehaviour(varchar类型),本文示例是int类型的状态存到数据库,所以只需要枚举类实现EnumBehaviour接口即可。其实这样做只是将重写了相应方法的公共部分抽离出来,以便项目中的所有枚举类使用。
public interface EnumBehaviour { int getValue(); String getDesc(); }
public interface EnumStringBehaviour { String getValue(); String getDesc(); }
下面是关于自动与DB映射转换的两个类,将至直接复制到项目中,按照后面的配置配置就可以了
DB保存int类型的
public class EnumValueTypeHandler extends BaseTypeHandler{ private Class type; private final EnumBehaviour[] enums; /** * 设置配置文件设置的转换类以及枚举类内容,供其他方法更便捷高效的实现 * * @param type 配置文件中设置的转换类 */ public EnumValueTypeHandler(Class type) { if (type == null) throw new IllegalArgumentException("Type argument cannot be null"); this.type = type; this.enums = type.getEnumConstants(); if (this.enums == null) throw new IllegalArgumentException(type.getSimpleName() + " does not represent an enum type."); } @Override public EnumBehaviour getNullableResult(ResultSet rs, String columnName) throws SQLException { // 根据数据库存储类型决定获取类型,本例子中数据库中存放INT类型 int i = rs.getInt(columnName); if (rs.wasNull()) { return null; } else { // 根据数据库中的code值,定位EnumBehaviour子类 return locateEnumBehaviour(i); } } @Override public EnumBehaviour getNullableResult(ResultSet rs, int columnIndex) throws SQLException { // 根据数据库存储类型决定获取类型,本例子中数据库中存放INT类型 int i = rs.getInt(columnIndex); if (rs.wasNull()) { return null; } else { // 根据数据库中的code值,定位EnumBehaviour子类 return locateEnumBehaviour(i); } } @Override public EnumBehaviour getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { // 根据数据库存储类型决定获取类型,本例子中数据库中存放INT类型 int i = cs.getInt(columnIndex); if (cs.wasNull()) { return null; } else { // 根据数据库中的code值,定位EnumBehaviour子类 return locateEnumBehaviour(i); } } @Override public void setNonNullParameter(PreparedStatement ps, int i, EnumBehaviour parameter, JdbcType jdbcType) throws SQLException { // baseTypeHandler已经帮我们做了parameter的null判断 ps.setInt(i, parameter.getValue()); } /** * 枚举类型转换,由于构造函数获取了枚举的子类enums,让遍历更加高效快捷 * * @param code 数据库中存储的自定义code属性 * @return code对应的枚举类 */ private EnumBehaviour locateEnumBehaviour(int code) { for (EnumBehaviour status : enums) { if (status.getValue() == code) { return status; } } throw new IllegalArgumentException("未知的枚举类型:" + code + ",请核对" + type.getSimpleName()); } }
DB保存varchar类型的
public class EnumStringValueTypeHandler extends BaseTypeHandler{ private Class type; private final EnumStringBehaviour[] enums; /** * 设置配置文件设置的转换类以及枚举类内容,供其他方法更便捷高效的实现 * * @param type 配置文件中设置的转换类 */ public EnumStringValueTypeHandler(Class type) { if (type == null) throw new IllegalArgumentException("Type argument cannot be null"); this.type = type; this.enums = type.getEnumConstants(); if (this.enums == null) throw new IllegalArgumentException(type.getSimpleName() + " does not represent an enum type."); } @Override public void setNonNullParameter(PreparedStatement ps, int i, EnumStringBehaviour parameter, JdbcType jdbcType) throws SQLException { // baseTypeHandler已经帮我们做了parameter的null判断 ps.setString(i, parameter.getValue()); } @Override public EnumStringBehaviour getNullableResult(ResultSet rs, String columnName) throws SQLException { // 根据数据库存储类型决定获取类型,本例子中数据库中存放VARCHAR类型 String str = rs.getString(columnName); if (rs.wasNull()) { return null; } else { // 根据数据库中的code值,定位EnumBehaviour子类 return locateStringEnumBehaviour(str); } } @Override public EnumStringBehaviour getNullableResult(ResultSet rs, int columnIndex) throws SQLException { // 根据数据库存储类型决定获取类型,本例子中数据库中存放VARCHAR类型 String str = rs.getString(columnIndex); if (rs.wasNull()) { return null; } else { // 根据数据库中的code值,定位EnumBehaviour子类 return locateStringEnumBehaviour(str); } } @Override public EnumStringBehaviour getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { // 根据数据库存储类型决定获取类型,本例子中数据库中存放VARCHAR类型 String str = cs.getString(columnIndex); if (cs.wasNull()) { return null; } else { // 根据数据库中的code值,定位EnumBehaviour子类 return locateStringEnumBehaviour(str); } } /** * 枚举类型转换,由于构造函数获取了枚举的子类enums,让遍历更加高效快捷 * * @param code 数据库中存储的自定义code属性 * @return code对应的枚举类 */ private EnumStringBehaviour locateStringEnumBehaviour(String code) { for (EnumStringBehaviour enumStringBehaviour : enums) { if (enumStringBehaviour.getValue().compareTo(code) == 0) { return enumStringBehaviour; } } throw new IllegalArgumentException("未知的枚举类型:" + code + ",请核对" + type.getSimpleName()); } }
下面是一个配置信息的xml,名字随便起,该xml配置了枚举类和想要映射到数据库的类型类的关系,一个int,一个varchar,也就是说你得告诉数据库你这个枚举放入数据库的值是啥吧?mybatis-config.xml
最后就是配置启动项了,你写了xml不得让项目去自己扫描使用吗?下面以springBoot为例:
在MybatisConfiguration类的下的sqlSessionFactoryBean中加入:bean.setConfigLocation(resolver.getResource("classpath:mybatis-config.xml"));然后就OK了,可以完美的使用了。
在sqlSessionFactory里加入xml地址就行,可以和我一样在java类里写也可以直接在配置文件中写都行。