mybatis枚举自动转换

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/joefany/article/details/82467908

因项目需要,在项目中需要实现mybatis 的枚举自动转换。

具体要求:可以根据枚举自定义属性在mybatis中自动转换。

1.先定义一个枚举基类

/**
 * 枚举基类
 * @author joefan
 * @create 2018年9月6日10:42:11
 */
public interface Identifiable {
    String DEFAULT_VALUE_NAME = "value";
    String DEFAULT_LABEL_NAME = "label";

    default Integer getValue() {
        Field field = ReflectionUtils.findField(this.getClass(), DEFAULT_VALUE_NAME);
        if (field == null)
            return null;
        try {
            field.setAccessible(true);
            return Integer.parseInt(field.get(this).toString());
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    @JsonValue
    default String getLabel() {
        Field field = ReflectionUtils.findField(this.getClass(), DEFAULT_LABEL_NAME);
        if (field == null)
            return null;
        try {
            field.setAccessible(true);
            return field.get(this).toString();
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    static <T extends Enum<T>> T valueOfEnum(Class<T> enumClass, Integer value) {
        if (value == null)
            throw new IllegalArgumentException("Identifiable value should not be null");
        if (enumClass.isAssignableFrom(Identifiable.class))
            throw new IllegalArgumentException("illegal Identifiable type");
        T[] enums = enumClass.getEnumConstants();
        for (T t : enums) {
            Identifiable displayedEnum = (Identifiable) t;
            if (displayedEnum.getValue().equals(value))
                return (T) displayedEnum;
        }
        throw new IllegalArgumentException("cannot parse integer: " + value + " to " + enumClass.getName());
    }
}

2.修改 SqlSessionFactoryBean方法,加入以下代码

    // 1.加入属性和get set 方法    
    //我们自定义的属性,扫描Enum的base package
	private String enumBasePackage;
	//我们自定义的属性,扫描Alias的base package
	private String aliasBasePackage;

	public String getEnumBasePackage() {
		return enumBasePackage;
	}

	public void setEnumBasePackage(String enumBasePackage) {
		this.enumBasePackage = enumBasePackage;
	}

	public String getAliasBasePackage() {
		return aliasBasePackage;
	}

	public void setAliasBasePackage(String aliasBasePackage) {
		this.aliasBasePackage = aliasBasePackage;
	}

   

    // 2.在buildSqlSessionFactory方法中加入以下代码
//alias
		if (null != this.aliasBasePackage && this.aliasBasePackage.trim().length() > 0) {
			ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
			resolverUtil.find(new ResolverUtil.IsA(BaseEntity.class), this.aliasBasePackage);
			//resolverUtil.find(new ResolverUtil.IsA(Identifiable.class), this.aliasBasePackage);
			Set<Class<? extends Class<?>>> mTypes = resolverUtil.getClasses();
			for (Class<?> javaTypeClass : mTypes) {
				logger.debug("Registered Alias : '" + javaTypeClass.getName() + "'");
				configuration.getTypeAliasRegistry().registerAlias(javaTypeClass);
			}
		}
		//enum
		if (this.enumBasePackage != null && this.aliasBasePackage.trim().length() > 0) {
			ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
			resolverUtil.find(new ResolverUtil.IsA(Identifiable.class), this.enumBasePackage);
			Set<Class<? extends Class<?>>> mTypes = resolverUtil.getClasses();
			for (Class<?> javaTypeClass : mTypes) {
				logger.debug("Registered Enum type handler: '" + javaTypeClass.getName() + "'->"+ EnumOrdinalTypeHandler.class.getName());
				configuration.getTypeAliasRegistry().registerAlias(javaTypeClass.getName(), javaTypeClass);
				configuration.getTypeAliasRegistry().registerAlias(javaTypeClass.getName().replace("$", "."), javaTypeClass);
				configuration.getTypeHandlerRegistry().register(javaTypeClass, DefaultEnumTypeHandler.class);
			}
		}
BaseEntity为实体类继承的基类,
Identifiable为枚举实现的接口
DefaultEnumTypeHandler为转换器,使我们自定义的,为了满足根据枚举自定义属性在mybatis中自动转换,如果只需要枚举的属性的下标转换只需要用默认的 mybatis的EnumOrdinalTypeHandler就行了

3.DefaultEnumTypeHandler转换器

public class DefaultEnumTypeHandler extends BaseTypeHandler<Identifiable> {

    private Class<Identifiable> type;

    public DefaultEnumTypeHandler(){};

    public DefaultEnumTypeHandler(Class<Identifiable> type) {
        if (type == null) throw new IllegalArgumentException("Type argument cannot be null");
        this.type = type;
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Identifiable parameter, JdbcType jdbcType)
            throws SQLException {
        ps.setInt(i, parameter.getValue());
    }

    @Override
    public Identifiable getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return convert(rs.getInt(columnName));
    }

    @Override
    public Identifiable getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return convert(rs.getInt(columnIndex));
    }

    @Override
    public Identifiable getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return convert(cs.getInt(columnIndex));
    }

    private Identifiable convert(int status){
        Identifiable[] objs = type.getEnumConstants();
        for(Identifiable em: objs){
            if(em.getValue() == status){
                return  em;
            }
        }
        return null;
    }
}

4.在spring的配置文件中配置 sqlSessionFactory的属性,用于配置扫描的包路径

<property name="aliasBasePackage" value="com.joefan.entity" />
<property name="enumBasePackage" value="com.joefan.entity" />

5.用法

    /**
	 * 类型
	 */
	public enum Type implements Identifiable {
		many("many", 10), 
		some("some", 20);

		String label;
		Integer value;

		Type(String label, Integer value) {
			this.label = label;
			this.value = value;
		}
	}

这样我们就可以根据10或者20 和枚举相互转换了

搞定!

猜你喜欢

转载自blog.csdn.net/joefany/article/details/82467908
今日推荐