chenjiahe
2022-04-06 e0e1d790b1e9137bb863b202c467d7f2e2e792ba
src/main/java/com/hx/mybatis/aes/springbean/InitMysqlData.java
@@ -3,7 +3,7 @@
import com.gitee.sunchenbin.mybatis.actable.annotation.Column;
import com.gitee.sunchenbin.mybatis.actable.annotation.Table;
import com.hx.common.annotations.MysqlHexAes;
import com.hx.common.dao.CommonMapper;
import com.hx.common.dao.mapper.CommonMapper;
import com.hx.common.service.CommonService;
import com.hx.exception.ServiceException;
import com.hx.mybatisTool.SqlSentence;
@@ -12,10 +12,9 @@
import javax.annotation.PostConstruct;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class InitMysqlData {
@@ -28,80 +27,169 @@
        //项目启动的时候填入
        if(!StringUtils.isEmpty(packPath)){
            Set<Class<?>> classes = VariableAesKey.classData(packPath);
            Map<String,String> aesKeysFild = new HashMap<>();
            boolean isAes = false;
            String tableName = null;
            String fildName = null;
            String fildValue = null;
            SqlSentence sqlSentence = new SqlSentence();
            Map<String,Object> values = new HashMap<>();
            for(Class<?> cl:classes){
                //表名称
                boolean hasAnnotation = cl.isAnnotationPresent(Table.class);
                if(!hasAnnotation){
            //解析表数据
            List<FieldData> fieldDatas = entityhandle(classes);
            int pageSize = 500;
            //创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
            ExecutorService fixedThreadPool = Executors.newFixedThreadPool(20);
            try{
                for(FieldData fieldData:fieldDatas){
                    //获取条数
                    sqlSentence.sqlSentence("SELECT COUNT(0) FROM "+fieldData.getTableName(),values);
                    int total = commonService.selectCountSql(sqlSentence);
                    if(total ==0 ){
                        continue;
                    }
                    int pageTotal = total/pageSize+1;
                    for(int i= 0;i<pageTotal;i++){
                        int finalI = i;
                        fixedThreadPool.execute(new Runnable() {
                            @Override
                            public void run() {
                                //更新数据
                                updateData(fieldData,commonService, finalI,pageSize);
                            }
                        });
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                fixedThreadPool.shutdown();
            }
        }
    }
    /**更新数据*/
    public static void updateData(FieldData fieldData,CommonService commonService,int pageNum,int pageSize){
        SqlSentence sqlSentence = new SqlSentence();
        Map<String,Object> values = new HashMap<>();
        //查询数据
        StringBuilder selectField = new StringBuilder();
        selectField.append(fieldData.getId());
        for(String fieldName:fieldData.getEncrypFields()){
            selectField.append(","+fieldName);
        }
        sqlSentence.sqlSentence("SELECT "+selectField.toString()+" FROM "+fieldData.getTableName()+" LIMIT "+pageNum+","+pageSize,values);
        List<Map<String,Object>> list = commonService.selectListMap(CommonMapper.class,sqlSentence);
        boolean isUpdate = false;
        for (Map<String,Object> map:list){
            isUpdate = false;
            StringBuilder setField = new StringBuilder();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                String mapKey = entry.getKey();
                String mapValue = (String) entry.getValue();
                if(StringUtils.isEmpty(mapValue)){
                    continue;
                }
                Table table = cl.getAnnotation(Table.class);
                tableName = table.name();
                if(mapValue.length()%32==0 && MysqlHexAesTool.isHexStrValid(mapValue)){
                    continue;
                }
                if(fieldData.getId().equals(mapKey)){
                    continue;
                }
                if(setField.length()>0){
                    setField.append(",");
                }
                setField.append(mapKey+" = #{m."+mapKey+"}");
                isUpdate = true;
            }
                aesKeysFild = new HashMap<>();
                isAes = false;
            if(isUpdate){
                values = map;
                sqlSentence.sqlSentence("UPDATE "+fieldData.getTableName()+" SET "+setField.toString()+" WHERE "+fieldData.getId()+" = #{m."+fieldData.getId()+"}",values);
                // 取得本类的全部属性
                Field[] fields = cl.getDeclaredFields();
                fields = VariableAesKey.getPatentFields(fields,cl);
                for (Field field:fields) {
                    fildName = null;
                    // 判断方法中是否有指定注解类型的注解
                    hasAnnotation = field.isAnnotationPresent(MysqlHexAes.class);
                    if (hasAnnotation) {
                        // 根据注解类型返回方法的指定类型注解
                        MysqlHexAes mysqlHexAes = field.getAnnotation(MysqlHexAes.class);
                        //String aesKeyField = mysqlHexAes.aesKeyField();
                        String aesKey = mysqlHexAes.aesKey();
                        if(StringUtils.isEmpty(aesKey)){
                            aesKey = VariableAesKey.AES_KEY;
                            if(StringUtils.isEmpty(aesKey)){
                                throw new RuntimeException("mysql的AES秘钥不能为空:"+field.getName());
                            }
                        }
                        hasAnnotation = field.isAnnotationPresent(Column.class);
                        if(hasAnnotation){
                            Column column = field.getAnnotation(Column.class);
                            fildName = column.name();
                        }
                        if(StringUtils.isEmpty(fildName)){
                            fildName = field.getName();
                        }
                        sqlSentence.sqlSentence("SELECT id,"+fildName+" FROM "+tableName,values);
                        List<Map<String,Object>> list = commonService.selectListMap(CommonMapper.class,sqlSentence);
                        for(Map<String,Object> map:list){
                            fildValue = (String)map.get(fildName);
                            System.out.println("fildValue:"+fildValue);
                            if(StringUtils.isEmpty(fildValue)){
                                continue;
                            }
                            if(fildValue.length()%32==0 && MysqlHexAesTool.isHexStrValid(fildValue)){
                                continue;
                            }
                            values.clear();
                            values.put("id",map.get("id"));
                            values.put("filedData",fildValue);
                            sqlSentence.sqlSentence("UPDATE "+tableName+" SET "+fildName+" = #{m.filedData} WHERE id = #{m.id}",values);
                            if(commonService.updateSentence(sqlSentence)!=1){
                                throw new ServiceException("更新超过1条,更新失败!");
                            }
                        }
                    }
                if(commonService.updateSentence(sqlSentence)!=1){
                    throw new ServiceException("更新超过1条,更新失败!");
                }
            }
        }
    }
    /**获取到表的数据*/
    public static List<FieldData> entityhandle(Set<Class<?>> classes){
        List<FieldData> fildDatas = new ArrayList<>();
        //存储单表字段信息
        FieldData fildData;
        //存储需要加密的字段
        Set<String> encrypFields;
        String fildName;
        for(Class<?> cl:classes){
            fildData = new FieldData();
            encrypFields = new HashSet<>();
            //表名称
            if(!cl.isAnnotationPresent(Table.class)){
                continue;
            }
            Table table = cl.getAnnotation(Table.class);
            fildData.setTableName(table.name());
            // 取得本类的全部属性
            Field[] fields = cl.getDeclaredFields();
            fields = VariableAesKey.getPatentFields(fields,cl);
            for (Field field:fields) {
                fildName = null;
                if(field.isAnnotationPresent(Column.class)){
                    Column column = field.getAnnotation(Column.class);
                    fildName = column.name();
                    if(StringUtils.isEmpty(fildName)){
                        fildName = field.getName();
                    }
                    if(column.isKey()){
                        fildData.setId(fildName);
                    }
                }else{
                    fildName = field.getName();
                }
                // 判断方法中是否有指定注解类型的注解
                if (!field.isAnnotationPresent(MysqlHexAes.class)) {
                    continue;
                }
                // 根据注解类型返回方法的指定类型注解
                MysqlHexAes mysqlHexAes = field.getAnnotation(MysqlHexAes.class);
                //判断版本号是不是一样的
                if(!StringUtils.isEmpty(VariableAesKey.INIT_VERSION)){
                    if(!VariableAesKey.INIT_VERSION.equals(mysqlHexAes.initVersion())){
                        continue;
                    }
                }else{
                    if(!StringUtils.isEmpty(mysqlHexAes.initVersion())){
                        continue;
                    }
                }
                String aesKey = mysqlHexAes.aesKey();
                if(StringUtils.isEmpty(aesKey)){
                    aesKey = VariableAesKey.AES_KEY;
                    if(StringUtils.isEmpty(aesKey)){
                        throw new RuntimeException("mysql的AES秘钥不能为空:"+field.getName());
                    }
                }
                encrypFields.add(fildName);
            }
            //是否有需要加密得字段
            if(encrypFields.size()<=0){
                continue;
            }
            fildData.setEncrypFields(encrypFields);
            fildDatas.add(fildData);
        }
        return fildDatas;
    }