关于业务中未冗余字段的其他表的字段进行映射
在我所做的业务中,写代码的时候基础的增删改查方法已经封装好,做单表查询是已经不需要写sql脚本。
所以经常遇到一个问题。假设数据库中有表Table,主键为id,有字段anyName。
在另一张表Ori表中的tableId字段存了Table表的主键id,现前端需要展示anyName,则需要写一个连表的sql去查出anyName。
所以做了一个字段映射的工具(该工具只是为了加快开发进度,对性能有要求的情况下不推荐使用)
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface PropertiesMap { /** * 对应基础数据中具体的类 * <p>基础数据来自{@link com.linsionxm.wms.utils.BasicObjName} 的全局常量
* EntityBase中有字段存了表名,所以限制传入的类需要是他的子类,可以根据实际情况调整 */ Class<? extends EntityBase> objClass() default VoidEntity.class; /** * 对应系统代码中具体的代码 * <p>系统代码来自{@link com.linsionxm.wms.basicdata.entitymodel.enums.CustDefCodeEnum} */ CustDefCodeEnum custCode() default CustDefCodeEnum.DEFAULT; /** * 对应的实体中基础数据id或系统代码 */ String keyName(); /** * 在使用基础数据做字段映射是可指定绑定对应的key,默认使用基础数据的id */ String keyField() default "id"; /** * 在使用基础数据做字段映射是可指定绑定对应的value,默认使用基础数据的name */ String keyValue() default "name"; /** * 取值类型,来自{@link S17BeanUtil}的全局常量 * <p>当取值为{@link S17BeanUtil#BASIC_OBJ_NAME}时,与{@link PropertiesMap#objClass()}配合使用, * 当取值为{@link S17BeanUtil#CUST_DEF_CODE}是,与{@link PropertiesMap#custCode()}配合使用 */ String type() default S17BeanUtil.BASIC_OBJ_NAME; }
@Component public class S17BeanUtil { /** * <p>根据{@link PropertiesMap}配置的字段映射信息对实体中的为冗余字段进行相应的字段映射</p> * * <p>如果{@link PropertiesMap#keyField()} 和 {@link PropertiesMap#keyValue()}没有进行配置,则默认使用“id” 和 “name”, * 这两个属性对应的是{@link PropertiesMap#objClass()}实体对应的数据库字段,如果字段无法匹配将会抛出一个sql异常。 * 通过配置的这两个属性,拼接一条查询{@link PropertiesMap#objClass()}实体对应的表的sql,最终结果拼接成一个 * {keyFiled,keyValue}对应值的Map。</p> * * <p>{@link PropertiesMap#keyName()}属性对应的是原始集合R中的字段,在做字段映射时通过改值去上文提到的map中检索到对应的value</p> * * <p>再举例之前,我们先定义一些我们用得到的对象</p> * <pre>{@code * class OriEntity { * //假定有一张表为table,该字段对应其主键id * //且该表中有一字段为anyName * private String tableId; * * //other field ... * //getter and setter ... * } * * * //table表中对用的数据 * { * "id":"1", * "anyName":"name1" * }, * { * "id":"2", * "anyName":"name2" * }, * //... 以此类推 * * * //现定义最终结果的映射对象 * class OriEntityVO extends OriEntity{ * @PropertiesMap(objClass = Table.class, * keyName = 'tableId', * keyField = 'id', * keyValue = 'anyName' * ) * private String anyName; * * //other field ... * //getter and setter ... * } * * * { * OriEntity oe1 = new OriEntity().setTableId("1"); * OriEntity oe2 = new OriEntity().setTableId("2"); * List<OriEntity> oriList = new ArrayList<>(); * List<OriEntityVO> resList = copyPropertiesAndFillingProperties(oriList, OriEntityVO.class); * /*最后可得到OriEntityVO集合为 * [ * { * "tableId":"1", * "anyName":"name1" * }, * { * "tableId":"2", * "anyName":"name2" * } * ] *\/ * * } * }</pre> * *<pre></pre> * @param resultList 需要进行字段映射的初始集合 * @param voClass 最终结果返回的集合类型 * @param <R> 原始类型 * @param <V> 最终类型 * @return 返回一个映射后的 V 类型的集合 * @throws Exception */ public static <R, V> List<V> copyPropertiesAndFillingProperties(List<R> resultList, Class<V> voClass) throws Exception { List<V> voList = new ArrayList<>(); Field[] fields = voClass.getDeclaredFields(); Map<Class<?> ,Map<String,String>> allMap = new HashMap<>(); for (R result : resultList) { V vo = voClass.newInstance(); BeanUtils.copyProperties(result, vo); for (Field field : fields) { if (field.isAnnotationPresent(PropertiesMap.class)) { PropertiesMap propertiesMap = field.getAnnotation(PropertiesMap.class); String keyName = propertiesMap.keyName(); String kfStr = propertiesMap.keyField(); String kvStr = propertiesMap.keyValue(); Field keyField = getField(voClass, keyName); keyField.setAccessible(true); field.setAccessible(true); Class<? extends EntityBase> objClass = propertiesMap.objClass(); List<String> keyList = resultList.stream() .map(i -> { try { Field rField = i.getClass().getDeclaredField(keyName); rField.setAccessible(true); return String.valueOf(rField.get(i)); } catch (NoSuchFieldException | IllegalAccessException e) { return ""; } }).distinct() .collect(Collectors.toList()); Map<String, String> nameMap = new HashMap<>(); if (!VoidEntity.class.getName().equals(objClass.getName())) { Map<String, String> map = allMap.getOrDefault(objClass, null); if (null == map) { map = BasicObjName.getMap(objClass, kfStr, kvStr, keyList); allMap.put(objClass, map); } nameMap = map; } String keyValue = Objects.toString(keyField.get(vo), ""); if (BASIC_OBJ_NAME.equals(propertiesMap.type())) { if (!VoidEntity.class.getName().equals(objClass.getName())) { field.set(vo, nameMap.get(keyValue)); } } else if (CUST_DEF_CODE.equals(propertiesMap.type())) { CustDefCodeEnum codeEnum = propertiesMap.custCode(); field.set(vo, staticCustDefCodeService.getNameByField(codeEnum.getCode(), keyValue)); } } } voList.add(vo); } return voList; } }
public static <R extends EntityBase> Map<String, String> getMap(Class<R> clazz, String keyField, String valueField, List<String> keyList) { try { String tableName = clazz.newInstance().getS17_TableName(); String sql = "select " + keyField + " as `key`," + valueField + " as value " + "from " + tableName; if (!CollectionUtils.isEmpty(keyList)) { List<String> param = new ArrayList<>(); keyList.forEach(key -> { param.add("'" + key + "'"); }); sql += " where " + keyField + " in (" + String.join(",", param) + ")"; } List<KeyAndValue> list = D_S17VOSqlMapper.selectList(staticDaoService.mySqlSession(), sql, KeyAndValue.class); return list.stream() .collect(Collectors.toMap( KeyAndValue::getKey, KeyAndValue::getValue, (oldV, newV) -> newV )); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); return new HashMap<>(); } }
@Data public class KeyAndValue { private String key; private String value; }

浙公网安备 33010602011771号