-
背景:
- 需要对敏感数据进行加密存储,处理历史数据时,需要执行批量查询明文字段,再将处理后的结果存储到密文字段
- 多张表都需要执行相同的操作
-
方案
使用反射映射到具体的dao层,执行具体的查询和更新方法,每次只需要变动入参
@Autowired
private ApplicationContext applicationContext;
public void batchUpdateEncrypt(String dao, String entity) throws Exception {
//获取dao层对象
Class daoClass = Class.forName(dao);
Object obj = applicationContext.getBean(daoClass);
//创建代理实例
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(obj);
Object proxy = proxyFactory.getProxy();
applicationContext.getAutowireCapableBeanFactory().autowireBean(obj);
Method getUsersByIdxMethod = daoClass.getMethod("getUsersByIdx", Long.class, Integer.class);
Long maxId = 0L;
Integer num = 0;
Integer count = 0;
while (true){
List<?> entityList = (List<?>) getUsersByIdxMethod.invoke(proxy, maxId, 2000);
if (CollectionUtil.isEmpty(entityList)){
break;
}
System.out.println(entityList);
Object lastEntity = entityList.get(entityList.size() - 1);
//获取实体类
Class entityClass = Class.forName(entity);
//取list中最后一个对象的id值
Field field = fieldId(entityClass);
if (field == null) {
log.info("这个类找不到id entity:{}", entity);
return;
}
field.setAccessible(true);
try {
Object lastIdx = field.get(lastEntity);
if (lastIdx instanceof Long) {
maxId = (Long) lastIdx;
} else {
log.error("Field is not of type Long. lastIdx: {}", lastIdx);
}
} catch (IllegalAccessException e) {
log.error("获取最后一个id值异常 ", e);
}
count += entityList.size();
Method updateBatchMethod = daoClass.getMethod("updateBatchEncrypt", List.class);
updateBatchMethod.invoke(proxy, entityList);
log.info("batchUpdateEncrypt 第{}次, 本次处理{}个数据", ++num, entityList.size());
}
log.info("batchUpdateEncrypt end 共处理{}个数据", count);
}
public Field fieldId(Class<?> clazz) {
while (clazz != null) {
Field[] declaredFields = clazz.getDeclaredFields();
List<Field> fieldId = Arrays.stream(declaredFields).filter(field -> "id".equals(field.getName())).collect(Collectors.toList());
if (CollectionUtil.isNotEmpty(fieldId)) {
return fieldId.get(0);
}
clazz = clazz.getSuperclass();
}
return null;
}
-
优缺分析
- 优点:不需要考虑具体表,公共处理
- 缺点:入参涉及到具体的类及路径,不友好