package com.product.data.center.service; import cn.hutool.core.util.NumberUtil; import com.product.common.lang.DateUtils; import com.product.core.dao.BaseDao; import com.product.core.entity.DataTableEntity; import com.product.core.entity.FieldSetEntity; import com.product.core.spring.context.SpringMVCContextHolder; import com.product.data.center.config.CmnConst; import com.product.datasource.dao.Dao; import com.product.datasource.entity.DataBaseEntity; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.*; import java.util.stream.Collectors; /** * @Author cheng * @Date 2022/11/26 15:17 * @Desc 订单数据同步验证 */ @Service public class OrderDataValidationService { @Resource private BaseDao baseDao; public synchronized void verificationEntryPoint() { // FieldSetEntity fse = baseDao.getFieldSetBySQL("select * from product_sys_order_data_verification limit 1", new Object[]{}, true); StringBuffer sql = new StringBuffer(); sql.append("\n SELECT "); sql.append("\n m.uuid, "); sql.append("\n m.data_source, "); sql.append("\n s.uuid sub_uuid, "); sql.append("\n table_name, "); sql.append("\n auto_field,is_date "); // sql.append("\n max_value, "); // sql.append("\n result "); sql.append("\n FROM "); sql.append("\n product_sys_order_data_verification m "); sql.append("\n INNER JOIN product_sys_order_data_verification_sub s ON s.master_uuid = m.uuid "); sql.append("\n AND m.is_used = 1 "); // sql.append("\n LEFT JOIN product_sys_order_data_verification_info i ON i.master_uuid = s.uuid "); // sql.append("\n AND result =1 "); DataTableEntity dte = baseDao.listTable(sql.toString(), (String[]) null); if (DataTableEntity.isEmpty(dte)) { return; } DataTableEntity sourceInfoDtb = baseDao.listTable("product_sys_order_data_verification_info", "id IN (select max(id) from product_sys_order_data_verification_info where length(max_value)>0 and result =1 GROUP BY data_source,table_name)", null, new Object[]{"max_value,data_source,table_name,master_uuid uuid,uuid m"}); // DataTableEntity subDt = fse.getSubDataTable("product_sys_order_data_verification_sub"); // if (DataTableEntity.isEmpty(subDt)) { // return; // } String[] dataSource = dte.getString(0, "data_source").split(","); if (dataSource.length <= 1) { //不足2个数据源无法对比 return; } DataBaseEntity[] sourceDataBase = new DataBaseEntity[dataSource.length]; for (int i = 0; i < dataSource.length; i++) { sourceDataBase[i] = new DataBaseEntity(dataSource[i]); } Map> map = new HashMap<>(); for (int i = 0; i < sourceDataBase.length; i++) { sql.setLength(0); DataBaseEntity dbe = sourceDataBase[i]; Dao dao = dbe.getDao(); try { for (int k = 0; k < dte.getRows(); k++) { if (k > 0) { sql.append("\n UNION ALL \n"); } FieldSetEntity fs = dte.getFieldSetEntity(k); String subUuid = fs.getString("sub_uuid"); String autoField = fs.getString("auto_field"); String tableName = fs.getString("table_name"); Boolean isDate = fs.getBoolean("is_date"); sql.append(" SELECT COUNT(1) num,"); if (isDate) { sql.append("to_char(MAX(").append(autoField).append("),'yyyy-mm-dd HH24:MI:SS') max"); sql.append(" ,to_char(MIN(").append(autoField).append("),'yyyy-mm-dd HH24:MI:SS') min "); } else { sql.append("to_char(MAX(").append(autoField).append(")) max"); sql.append(" ,to_char(MIN(").append(autoField).append(")) min "); } String maxValue = ""; if (!DataTableEntity.isEmpty(sourceInfoDtb) && sourceInfoDtb.getFieldSetEntity(subUuid) != null) { FieldSetEntity f = sourceInfoDtb.getFieldSetEntity(subUuid).stream().filter(item -> item.getString("data_source").equals(dbe.getUuid()) && item.getString("table_name").equals(tableName)).findFirst().get(); maxValue = f.getString("max_value"); } sql.append(",'" + (StringUtils.isEmpty(tableName) ? "" : tableName) + "' table_name,'" + maxValue + "' max_value"); sql.append(" FROM ").append(tableName); fs.setValue("max_value", maxValue); if (!StringUtils.isEmpty(maxValue)) { sql.append(" WHERE ").append(autoField).append("> "); if (isDate) { sql.append(" to_date('" + fs.getDate("max_value", "yyyy-MM-dd HH:mm:ss") + "','yyyy-mm-dd HH24:MI:SS')"); } else { sql.append("to_char('" + maxValue + "')"); } } } DataTableEntity dt = dao.getList(sql.toString(), (Object[]) null); for (int j = 0; j < dt.getRows(); j++) { String tableName = dt.getString(j, "table_name"); List resultEntities = map.computeIfAbsent(tableName, k -> new ArrayList<>()); resultEntities.add(new ResultEntity(dt.getFieldSetEntity(j), dbe)); } } catch (Exception e) { e.printStackTrace(); throw e; } finally { if (dao != null) { dao.closeConnection(); } } } DataTableEntity infoDte = new DataTableEntity(); map.forEach((k, v) -> { StringBuilder message = new StringBuilder(64); //获取最大的num结果 ResultEntity maxResult = v.stream().max(Comparator.comparingInt(ResultEntity::getNum)).get(); int totalCount = maxResult.getNum(); if (totalCount <= 0) { //最大0条 return; } //过滤出小于num 或者 最大最小值不一致的 List collect = v.stream().filter(item -> item.getNum() < totalCount).collect(Collectors.toList()); boolean result = false; if (collect != null && collect.size() > 0) { //当前循环的表验证不通过,数量不一致 message.append("校验结果不一致!\n"); for (int i = 0; i < collect.size(); i++) { ResultEntity resultEntity = collect.get(i); DataBaseEntity dbe = resultEntity.getDbe(); message.append("\nERROR:" + (i + 1)); message.append("\n\t\t错误的连接名称:" + dbe.getConnectionName()); message.append("\n\t\t错误的表名:" + resultEntity.getTableName()); message.append("\n\t\t因总条数不一致判定为错误,本次最大总条数为:" + maxResult.getNum() + ",来自于连接名称:" + maxResult.getDbe().getConnectionName()); message.append("\n\t\t截止上一次成功的最大值:" + resultEntity.getLastMaxValue()); message.append("\n\t\t当前总条数:" + resultEntity.getNum()); } } else { //验证通过 message.append("校验成功,总条数一致 !"); result = true; } message.append("\n校验时间:" + DateUtils.getDate("yyyy-MM-dd HH:mm:ss")); Date date = new Date(); for (int i = 0; i < v.size(); i++) { FieldSetEntity infoFse = new FieldSetEntity(); infoFse.setTableName("product_sys_order_data_verification_info"); infoFse.setValue("result", result ? 1 : 0); ResultEntity resultEntity = v.get(i); infoFse.setValue("data_source", resultEntity.getDbe().getUuid()); infoFse.setValue("table_name", resultEntity.getTableName()); infoFse.setValue("max_value", resultEntity.getMaxValue()); FieldSetEntity filter = dte.getData().stream().filter(item -> resultEntity.getTableName().equals(item.getString("table_name"))).findFirst().get(); infoFse.setValue("master_uuid", filter.getString("sub_uuid")); infoFse.setValue("message", message.toString()); System.out.println(message.length()); infoFse.setValue(CmnConst.CREATED_UTC_DATETIME, date); infoDte.addFieldSetEntity(infoFse); } }); if (!DataTableEntity.isEmpty(infoDte)) { try { baseDao.add(infoDte); } catch (Exception e) { SpringMVCContextHolder.getSystemLogger().error(e); e.printStackTrace(); } } } class ResultEntity { private int num; private String minValue; private String maxValue; private String tableName; private String lastMaxValue; private DataBaseEntity dbe; public ResultEntity(FieldSetEntity fse, DataBaseEntity dbe) { this.num = NumberUtil.parseInt(fse.getString("num")); this.minValue = fse.getString("min"); this.maxValue = fse.getString("max"); this.lastMaxValue = fse.getString("max_value"); this.tableName = fse.getString("table_name"); this.dbe = dbe; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public String getMinValue() { return minValue; } public void setMinValue(String minValue) { this.minValue = minValue; } public String getMaxValue() { return maxValue; } public void setMaxValue(String maxValue) { this.maxValue = maxValue; } public String getTableName() { return tableName; } public void setTableName(String tableName) { this.tableName = tableName; } public String getLastMaxValue() { return lastMaxValue; } public void setLastMaxValue(String lastMaxValue) { this.lastMaxValue = lastMaxValue; } public DataBaseEntity getDbe() { return dbe; } public void setDbe(DataBaseEntity dbe) { this.dbe = dbe; } } }