描述

项目牵扯到了jpa和mybatis,枚举映射的值类型有字符串,数值,自定义信息,所以统一了一下规则,方便开发,反正我觉得很好用

举例

enum Weekday {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY 
}

字符串可以使用 
@Enumerated(EnumType.STRING)
这个是按照枚举的枚举值的名称进行存储
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY 

数值可以使用
@Enumerated(EnumType.ORDINAL)
这个是按照枚举的枚举值的次序进行存储
0,1,2,3,4,5,6
如果我想存储的时候SUNDAY代表的是0, 那么就要改变顺序,如果已经上线了,就可能带来很大的风险

实战

//枚举类字段的使用
/**
 * 星期 1.星期一 2.星期二 3.星期三 4.星期四 5.星期五 6.星期六 7.星期日
 */
@ApiModelProperty("星期 1.星期一 2.星期二 3.星期三 4.星期四 5.星期五 6.星期六 7.星期日")
//mybatis-plus字段映射 ,@Result字段映射
@TableField(value = "weekday", typeHandler = Weekday.WeekdayConverter.class)
//反序列化的场景是前端传值时可以自定义使用
@JsonDeserialize(using = Weekday.WeekdayJsonDeserializer.class)
//序列化为枚举继承的泛型类型值, 例如:redis缓存,json相应数据等
@JsonSerialize(using = EnumConstant.EnumJsonSerializer.class)
//jpa框架字段映射
@Convert(converter = Weekday.WeekdayConverter.class)
//jpa字段映射信息
@Column(name = "weekday", columnDefinition = "tinyint NOT NULL DEFAULT 1  COMMENT '星期 1.星期一 2.星期二 3.星期三 4.星期四 5.星期五 6.星期六 7.星期日'")
private Weekday weekday;
//枚举类
public enum Weekday implements EnumConstant<Integer> {

   //星期一
   MONDAY(1, 1, "星期一", "悲催的周一"),
   //星期二
   TUESDAY(2, 2, "星期二", "周二我爱摸鱼"),
   //星期三
   WEDNESDAY(3, 3, "星期三", "调休去看电影"),
   //星期四
   THURSDAY(4, 4, "星期四", "期待中度过"),
   //星期五
   FRIDAY(5, 5, "星期五", "哼着欢快的小曲"),
   //星期六
   SATURDAY(6, 6, "星期六", "加班吐血中"),
   //星期日, 
   //注意这里的类型值是0
   SUNDAY(0, 7, "星期日", "吸血鬼继续压榨");

	Weekday(Integer typeValue, Integer value, String name, String showInfo) {
		this.typeValue = typeValue;
		this.value = value;
		this.name = name;
		this.showInfo = showInfo;
	}

	/**
	 * 类型值,没想好怎么用,保留
	 */
	private final Integer typeValue;

	/**
	 * 枚举值
	 */
	private final Integer value;

	/**
	 * 枚举名称
	 */
	private final String name;

	/**
	 * 展示信息
	 */
	private final String showInfo;

	/**
	 * 获取默认值
	 * 如果需要就返回,不需要就不返回
	 *
	 * @return 这里返回的默认的周一
	 */
	@Override
	public Integer getDefaultValue() {
		return MONDAY.getValue();
	}

	/**
	 * 获取枚举值
	 *
	 * @return 枚举值
	 */
	@Override
	public Integer getValue() {
		return this.value;
	}

	/**
	 * 获取枚举名称
	 *
	 * @return 名称
	 */
	@Override
	public String getName() {
		return this.name;
	}

	/**
	 * 获取枚举展示信息
	 * 可以在导出报表的时候作为直接展示使用,或者是返回给前端直接使用
	 * 这个方法复写了父类
	 *
	 * @return 展示信息
	 */
	@Override
	public String getExportShowValue() {
		return this.showInfo;
	}


	/**
	 * mybatis与jpa框架数据库枚举字段转换
	 * 如果没有使用到相应的框架, 可以把相应的继承或实现的代码删除
	 * 如果不使用jpa框架,@Converter可以不写
	 */
	public static class WeekdayConverter extends AbstractEnumConverter<Weekday, Integer> {
	}

	/**
	 * 自定义json反序列化
	 */
	public static class WeekdayJsonDeserializer extends EnumJsonDeserializer<EnumConstant<Integer>, Integer> {

		@Override
		public Weekday deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
			ObjectCodec codec = p.getCodec();
			String value = codec.readValue(p, String.class);
			Weekday[] enumConstants = Weekday.values();
			for (Weekday enumConstant : enumConstants) {

				//这里使用显示信息反序列化枚举
				//例如前端传值为"哼着欢快的小曲",则为星期五,枚举值为FRIDAY
				if (enumConstant.getExportShowValue().equals(value)) {
					return enumConstant;
				}
			}
			throw new IllegalArgumentException("没有找到值");
		}
	}
}

//继承的枚举常量信息
public interface EnumConstant<T> {

	/**
	 * 获取默认值
	 *
	 * @return
	 */
	default T getDefaultValue() {
		return null;
	}

	/**
	 * 获取枚举值
	 *
	 * @return 枚举值
	 */
	T getValue();

	/**
	 * 获取名称
	 *
	 * @return 名称
	 */
	String getName();

	/**
	 * 导出excel等的显示值
	 *
	 * @return 显示值
	 */
	default String getExportShowValue() {
		return getName();
	}

	default EnumConstant<T> getDefault() {
		return null;
	}

	/**
	 * 是否使用默认
	 *
	 * @return 默认否
	 */
	default boolean whetherUseDefault() {
		return false;
	}

	default void setFieldValue(T value) {
	}

	default T getFieldValue() {
		return null;
	}

	/**
	 * 根据值获取枚举
	 *
	 * @param value 值
	 * @return 枚举
	 */
	default EnumConstant<T> findByValue(T value) {
		Class<? extends EnumConstant<T>> aClass = (Class<? extends EnumConstant<T>>) this.getClass();

		EnumConstant<T>[] enumConstants = aClass.getEnumConstants();
		if (Objects.isNull(enumConstants) || 0 == enumConstants.length) {
			throw new IllegalArgumentException("没有找到值");
		}
		for (EnumConstant<T> enumConstant : enumConstants) {
			if (enumConstant.getValue().equals(value)) {
				return enumConstant;
			}
		}
		throw new IllegalArgumentException("没有找到值");
	}

	/**
	 * mybatis框架与jpa框架枚举类型自定义转换
	 */
	abstract class AbstractEnumConverter<E extends EnumConstant<T>, T> extends BaseTypeHandler<EnumConstant<T>> implements AttributeConverter<EnumConstant<T>, T> {

		protected Class<E> constant;

		{
			constant = (Class<E>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		}

		public E getDefault() {
			return null;
		}

		@Override
		public void setNonNullParameter(PreparedStatement ps, int i, EnumConstant<T> parameter, JdbcType jdbcType) throws SQLException {
			T value = parameter.getValue();
			ps.setObject(i, value);
		}

		@Override
		public EnumConstant<T> getNullableResult(ResultSet rs, String columnName) throws SQLException {
			T columnValue = (T) rs.getObject(columnName);
			return getValue(columnValue);

		}

		@Override
		public EnumConstant<T> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
			T columnValue = (T) rs.getObject(columnIndex);
			return getValue(columnValue);

		}

		@Override
		public EnumConstant<T> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
			T columnValue = (T) cs.getObject(columnIndex);
			return getValue(columnValue);
		}

		/**
		 * 根据值获取枚举
		 *
		 * @param columnValue 值
		 * @return 枚举
		 */
		public EnumConstant<T> getValue(T columnValue) {
			EnumConstant<T>[] enumConstants = constant.getEnumConstants();
			if (Objects.isNull(enumConstants) || 0 == enumConstants.length) {
				throw new IllegalArgumentException("没有找到值");
			}
			for (EnumConstant<T> enumConstant : enumConstants) {
				if (enumConstant.getValue().equals(columnValue)) {
					return enumConstant;
				}
			}
			EnumConstant<T> defaultEnum = getDefault();
			if (Objects.isNull(defaultEnum)) {
				throw new IllegalArgumentException("没有找到值");
			}
			return defaultEnum;
		}

		/**
		 * 转换枚举到数据库字段
		 *
		 * @param enumConstant the entity attribute value to be converted
		 * @return 存储数据
		 */
		@Override
		public T convertToDatabaseColumn(EnumConstant<T> enumConstant) {
			if (Objects.isNull(enumConstant)) {
				throw new IllegalArgumentException("转换参数为空");
			}
			return enumConstant.getValue();
		}

		/**
		 * 转换数据为枚举
		 *
		 * @param value the data from the database column to be
		 *              converted
		 * @return 枚举数据
		 */
		@SneakyThrows
		@Override
		public EnumConstant<T> convertToEntityAttribute(T value) {
			return this.getValue(value);
		}

	}

	/**
	 * json序列化
	 */
	class EnumJsonSerializer<E extends EnumConstant<T>, T> extends JsonSerializer<EnumConstant<T>> {

		@Override
		public void serialize(EnumConstant<T> value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
			gen.writeObject(value.getValue());
		}
	}

	/**
	 * json反序列化
	 */
	class EnumJsonDeserializer<E extends EnumConstant<T>, T> extends JsonDeserializer<EnumConstant<T>> {

		@Override
		public EnumConstant<T> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
			ObjectCodec codec = p.getCodec();
			Field field = findField(p.getCurrentName(), p.getCurrentValue().getClass());
			Class<E> e = (Class<E>) field.getType();
			Type[] genericInterfaces = e.getGenericInterfaces();
			ParameterizedType genericInterface = (ParameterizedType) genericInterfaces[0];
			Class<T> t = (Class<T>) genericInterface.getActualTypeArguments()[0];
			T value = codec.readValue(p, t);

			EnumConstant<T>[] enumConstants = e.getEnumConstants();
			if (Objects.isNull(enumConstants) || 0 == enumConstants.length) {
				throw new IllegalArgumentException("没有找到值");
			}
			for (EnumConstant<T> enumConstant : enumConstants) {
				if (enumConstant.getValue().equals(value)) {
					return enumConstant;
				}
			}

			EnumConstant<T> defaultEnum = enumConstants[0].getDefault();
			if (Objects.isNull(defaultEnum)) {
				throw new IllegalArgumentException("没有找到值");
			}
			if (!defaultEnum.whetherUseDefault()) {
				throw new IllegalArgumentException("没有找到值");
			}
			return defaultEnum;
		}

		public Field findField(String name, Class<?> c) {
			for (; c != null; c = c.getSuperclass()) {
				for (Field field : c.getDeclaredFields()) {
					if (Modifier.isStatic(field.getModifiers())) {
						continue;
					}
					if (field.getName().equals(name)) {
						return field;
					}
				}
			}
			return null;
		}
	}

}

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐