多张表执行批量查询更新操作公共方法

32 阅读1分钟
  1. 背景:

  • 需要对敏感数据进行加密存储,处理历史数据时,需要执行批量查询明文字段,再将处理后的结果存储到密文字段
  • 多张表都需要执行相同的操作
  1. 方案

使用反射映射到具体的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;
}
  1. 优缺分析

  • 优点:不需要考虑具体表,公共处理
  • 缺点:入参涉及到具体的类及路径,不友好