自定义注解+反射在excel导入时获取字典表字段对应的值
1、思路:
用反射得到实体的上的自定义注解 ,从字典表数据源中找到注解对应的值,不用写很多重复代码,但是并不会改善效率,需要注意的地方就是查询字典表数据的接口一定要加缓存机制,不然循环查数据库就很恐怖;还有就是像行政区划这种很容易重名的字段表不太好使,因为我将字典表数据的值作为map的key,id作为map的value,重名要报错,只有单独写方法去匹配,说到底这种几十上百个字段的实体就不应该导入,还要校验数据,细节根本抠不完,我快遭不住了
2、注解:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DictTranslate
{
/**
* 字典表名称
* @return 字典表名称
*/
String dataSource();
/**
* 目标字段
* @return 目标字段
*/
String targetField();
}
3、反射处理
/**
* 匹配 字典表 mc 字段 ;将wid值赋值给targetfield字段
*
* @param dataList dataList
*/
public <T> void parseDictText(List<T> dataList)
{
if (CollectionUtils.isNotEmpty(dataList))
{
for (int i = 0; i < dataList.size(); i++)
{
T result = dataList.get(i);
Field[] fields = result.getClass().getDeclaredFields();
for (Field field : fields)
{
//检查带有 【DictTranslate】的注解
DictTranslate annotation = field.getAnnotation(DictTranslate.class);
if (annotation != null)
{
String dataSource = annotation.dataSource();
String targetFieldStr = annotation.targetField();
field.setAccessible(true);
try
{
String fieldValue = (String) field.get(result);
if (StringUtils.isNotEmpty(fieldValue))
{
//查询字典表
DictPojo dictPojo = new DictPojo();
dictPojo.setTableName(dataSource);
List<TbzGbBsHbhZjDto> dictList = dictApiService.findDictDataByTableName(dictPojo);
//名称作为key wid作为value
// TODO: 2022/3/5 行政区划有重名
String s = null;
if (CollectionUtils.isNotEmpty(dictList))
{
Map<String, String> collect = dictList.stream().collect(Collectors.toMap(TbzGbBsHbhZjDto::getMc, TbzGbBsHbhZjDto::getWid));
s = collect.get(fieldValue);
} else
{
log.info("字典表不存在:" + dataSource);
}
//匹配字段
Field targetField = result.getClass().getDeclaredField(targetFieldStr);
targetField.setAccessible(true);
if (StringUtils.isNotEmpty(s))
{
targetField.set(result, s);
} else
{
//-1代表错误不能导入
//targetField.set(result, "-1");
Excel excelAnno = field.getAnnotation(Excel.class);
if (excelAnno != null)
{
throw new CommonException("第【" + (i+2) + "】行 【" + excelAnno.name() + "】 不存在于系统中");
} else
{
throw new CommonException("导入失败");
}
}
targetField.setAccessible(false);
}
} catch (IllegalAccessException | NoSuchFieldException e)
{
log.error(e.getMessage());
} finally
{
field.setAccessible(false);
}
}
}
}
}
}
4、举例:
(1)这是教职工基本信息的实体类其中的性别字段:
@ApiModelProperty(value = "<字典表> T_BZGB_XB 性别 GB/T 2261.1")
@TableField("XBM")
private String xbm;
@ApiModelProperty(value = "性别")
@Excel(name = "性别")
@DictTranslate(dataSource = "T_BZGB_XB",
targetField = "xbm")
@TableField(exist = false)
private String xbmc;
(2)使用easypoi导入
/**
* 导入教职工信息
*
* @param file file
*/
public void importJzg(MultipartFile file) throws Exception
{
List<JzgJbxxEntity> jzgList = ExcelImportUtil.importExcel(file.getInputStream(), JzgJbxxEntity.class, new ImportParams());
dictTranslateService.parseDictText(jzgList);
log.info("导入中....")
}
(3)打个断点看到效果: