数据库字典转换

mac2024-03-11  52

字典转换工具类

package com.example.demo; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.util.Assert; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; /** * @author shanks on 2019-10-25 */ @Slf4j public class DataFormatter { /** * 翻译当前类中需要翻译的字典值 * * @param source 待翻译的对象 */ public static <T> void dataFormatter(T source) { //判断原对象是否为null Assert.notNull(source, "待翻译的原对象不能为null"); //获取所有属性并翻译字典 Field[] declaredFields = source.getClass().getDeclaredFields(); //翻译字典:找出所有含有@CacheFormatter的属性 Stream<Field> fieldStream = Arrays.stream(declaredFields) //排除没有注解@CacheFormatter的字段 .filter(field -> field.isAnnotationPresent(CacheFormat.class)); //翻译 doFormatter(fieldStream, source, source.getClass()); } /** * 翻译当前集合类中需要翻译的字典值 * * @param sources 待翻译的集合对象 */ public static <T> void dataFormatter(List<T> sources) { //当翻译的集合为空时,返回空的集合 if (sources == null || sources.isEmpty()) { return; } Class targetClass = sources.get(0).getClass(); //获取所有属性并翻译字典 Field[] declaredFields = targetClass.getDeclaredFields(); //翻译字典:找出所有含有@CacheFormat的属性集合 List<Field> formatterFields = Arrays.stream(declaredFields) //排除没有注解@CacheFormat的字段 .filter(field -> field.isAnnotationPresent(CacheFormat.class)) .collect(Collectors.toList()); //循环列表(并行操作) sources.parallelStream().forEach(target -> { //翻译 doFormatter(formatterFields.stream(), target, targetClass); }); } /** * 把原对象转换成目标类的对象,并翻译目标类的属性字典 * 只针对目标类没有范型或者范型与原对象一样 * @param source 原对象 * @param targetClass 目标类 * @return 目标对象 */ public static <T> T dataConvert(Object source, Class<T> targetClass) { Assert.isTrue(source != null && targetClass != null, "原对象或目标class不能为null"); T target = BeanUtils.instantiateClass(targetClass); //把目标对象的属性设置成原对象中对应的属性 BeanUtils.copyProperties(source, target); dataFormatter(target); return target; } /** * 实体属性互转 * * @param source 原对象 * @param target 目标对象 * @return 目标对象 */ public static <T> T dataObjConvert(Object source, T target) { Assert.isTrue(source != null && target != null, "待转换的原对象或目标对象不能为null"); //转换 BeanUtils.copyProperties(source, target); //翻译 dataFormatter(target); return target; } /** * 批量把原对象转换成目标对象,并翻译目标对象的属性字典 * 如果想返回指定类型的集合即List的子类,参考{@link HyBeanUtils#dataConverts2} * * @param sources 原对象集合 * @param targetClass 目标对象的类 * @return 返回转换后的目标集合 */ public static <T, E> List<T> dataConverts(List<E> sources, Class<T> targetClass) { Assert.notNull(targetClass, "转换的目标Class不能为null"); //当翻译的集合为空时,返回空的集合 if (sources == null || sources.isEmpty()) { List<T> targetList = new ArrayList<>(); return targetList; } //获取原集合的类型 Class<? extends List> aClass = sources.getClass(); //目标集合 List targetList = BeanUtils.instantiateClass(aClass); //把目标对象的属性设置成原对象中对应的属性(并行操作) sources.parallelStream().forEach(item -> { T target = BeanUtils.instantiateClass(targetClass); BeanUtils.copyProperties(item, target); targetList.add(target); }); //翻译字典 dataFormatter(targetList); return targetList; } /** * 返回指定类型的方法,这里的类型必须是List的子类 * 批量把原对象转换成目标对象,并翻译目标对象的属性字典, * * @param sources 原对象集合 * @param targetClass 目标对象的类 * @param returnType 返回值类型 * @return 返回转换后的目标集合 */ public static <T, E, R extends List<T>> R dataConverts2(List<E> sources, Class<T> targetClass, Class<R> returnType) { Assert.notNull(targetClass, "转换的目标Class不能为null"); Assert.notNull(returnType, "返回值类型Class不能为null"); //当翻译的集合为空时,返回空的集合 if (sources == null || sources.isEmpty()) { return null; } //目标集合 R targetList = BeanUtils.instantiateClass(returnType); //把目标对象的属性设置成原对象中对应的属性(并行操作) sources.parallelStream().forEach(item -> { T target = BeanUtils.instantiateClass(targetClass); BeanUtils.copyProperties(item, target); targetList.add(target); }); //翻译字典 dataFormatter(targetList); return targetList; } /** * 对目标类需要翻译的字段进行翻译 * * @param stream * @param target 目标对象 * @param targetClass 目标对象类 */ private static <T> void doFormatter(Stream<Field> stream, Object target, Class<T> targetClass) { //排除目标对象中字段值为null的字段 stream.filter(field -> { PropertyDescriptor propertyDescriptor = BeanUtils.getPropertyDescriptor(targetClass, field.getName()); Object invoke = null; try { invoke = propertyDescriptor.getReadMethod().invoke(target); } catch (IllegalAccessException e) { log.warn("待翻译的字段的get是无法访问的", e); } catch (InvocationTargetException e) { log.warn("调用待翻译的字段的get方法时报错", e); } catch (Exception e) { log.warn("确保属性有get,set方法", e); } return invoke != null; //遍历需要翻译的字段 }).forEach(field -> { CacheFormat annotation = field.getAnnotation(CacheFormat.class); //缓存系统编号,如果不指定则默认为当前系统编号 String systemCode = "system_code"; if (StringUtils.isNotBlank(annotation.systemCode())) { systemCode = annotation.systemCode(); } //缓存key,如果不指定,则默认为字段名称 String key = annotation.key(); if (StringUtils.isBlank(key)) { key = field.getName(); } //判断注解@CacheFormatter是否指定把字典翻译到另一个字段上 String formatterField = annotation.destination(); if (StringUtils.isBlank(formatterField)) { //当注解中不指定其他字段时,默认翻译到加注解的属性上 formatterField = field.getName(); } try { PropertyDescriptor orginPropertyDescriptor = BeanUtils.getPropertyDescriptor(targetClass, field.getName()); Object value = orginPropertyDescriptor.getReadMethod().invoke(target); //设置目标字段值 PropertyDescriptor propertyDescriptor = BeanUtils.getPropertyDescriptor(targetClass, formatterField); //取缓存 String cacheValue = RedisUtils.hget(systemCode +":valueset:" + key, value + ""); //如果数据字典中查询不到,则取业务缓存中取 if (StringUtils.isBlank(cacheValue)) { cacheValue = RedisUtils.hget(systemCode + ":valueset:" + key, value + ""); } Assert.hasLength(cacheValue, "在缓存" + key + "中没有找到" + value + "对应的缓存"); //设置缓存值到属性字段中 propertyDescriptor.getWriteMethod().invoke(target, cacheValue); } catch (IllegalAccessException e) { log.warn("待翻译的字段的set是无法访问的", e); } catch (InvocationTargetException e) { log.warn("调用待翻译的字段的set方法时报错", e); } catch (Exception e) { log.warn("调用待翻译的字段的set方法时报错,推测类型不匹配", e); } }); } }

注解类

package com.example.demo; import java.lang.annotation.*; /** * @author muyl */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface CacheFormat { /** * 缓存key * @return */ String key(); /** * 指定翻译值存放字段, 例如:userType的翻译结果放到userTypeName上 * @return */ String destination() default ""; /** * 系统编号 * @return */ String systemCode() default ""; }

工具类

package com.example.demo; /** * @author shanks on 2019-10-25 */ public class RedisUtils { public static String hget(String s, String s1) { return "男"; } }
最新回复(0)