抽象策略类:
AbstractCalcuateRuleValueStrategy.java
package cn.getech.data.manager.service.strategy;
import cn.getech.data.manager.constant.DayTypeEnum;
import cn.getech.data.manager.constant.RuleExpectedTypeEnum;
import cn.getech.data.manager.entity.DataQualityExcelDaily;
import cn.getech.data.manager.entity.DataQualityRuleDaily;
import cn.getech.data.manager.entity.DataQualityRulePartitionField;
import cn.getech.data.manager.model.dto.CalcuateRuleValueDto;
import cn.getech.data.manager.model.dto.RuleStatisticValueDto;
import cn.getech.data.manager.model.dto.TableStatisticValueDto;
import cn.getech.data.manager.model.vo.RuleDataRowVO;
import cn.getech.data.manager.model.vo.TableStatisticValueVO;
import cn.getech.data.manager.service.*;
import cn.getech.data.manager.service.factory.TableStatisticStrategyFactory;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.PageUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xxl.job.core.log.XxlJobLogger;
import org.springframework.beans.factory.annotation.Autowired;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
public abstract class AbstractCalcuateRuleValueStrategy {
@Autowired
protected IDataQualityRuleService dataQualityRuleService;
@Autowired
private IDataQualityRuleDailyService dataQualityRuleDailyService;
@Autowired
private CalculateVolatilityService calculateVolatilityService;
@Autowired
private IDataQualityExcelDailyService dataQualityExcelDailyService;
@Autowired
private IDataQualityRulePartitionFieldService dataQualityRulePartitionFieldService;
/**
* @Description 通过规则计算出实际值
* @Author chengweiping
* @Date 2020/10/12 23:20
*/
public final RuleStatisticValueDto calcuateValueByRule(CalcuateRuleValueDto calcuateRuleValueDTO){
RuleStatisticValueDto ruleStatisticValueDto=new RuleStatisticValueDto();
// 1:固定值 2:波动率
Integer ruleExpectedType= calcuateRuleValueDTO.getRuleExpectedType();
Integer connectId=calcuateRuleValueDTO.getConnectId();
DataSourceStrategy dataSourceStrategy=dataQualityRuleService.getDataSourceStrategyByConnectId(connectId);
//获取今天规则的统计值
BigDecimal dayStatisValueDB= new BigDecimal(0);
try {
Long ruleId=calcuateRuleValueDTO.getRuleId();
QueryWrapper queryWrapper=new QueryWrapper();
queryWrapper.eq("rule_id",ruleId);
//设置分区字段
List<DataQualityRulePartitionField> partitionFieldList= dataQualityRulePartitionFieldService.list(queryWrapper);
calcuateRuleValueDTO.setPartitionFieldList(partitionFieldList);
//获取今天计算的统计值
dayStatisValueDB = getTodayDayStatisValue(calcuateRuleValueDTO,dataSourceStrategy);
XxlJobLogger.log("getTodayDayStatisValue,规则当前调用结果={}", JSON.toJSON(dayStatisValueDB));
} catch (Exception e) {
e.printStackTrace();
}
try {
if(RuleExpectedTypeEnum.FIXED_VALUE.getCode().equals(ruleExpectedType)){
ruleStatisticValueDto.setStatisticValue(dayStatisValueDB);
ruleStatisticValueDto.setDayStatisticValuve(dayStatisValueDB);
}else{
//波动率计算
LocalDate today=LocalDate.now();
//之前的天数
Integer dayType= calcuateRuleValueDTO.getDayType();
Integer day=0;
//根据天数类型就是真实相差的天数
if(dayType==null || DayTypeEnum.DAY.getCode().equals(dayType)){
day=calcuateRuleValueDTO.getDay();
}else if(dayType==null || DayTypeEnum.MONTH.getCode().equals(dayType)){
day=calcuateRuleValueDTO.getDay()*DayTypeEnum.MONTH.getNum();
}else if(dayType==null || DayTypeEnum.YEAR.getCode().equals(dayType)){
day=calcuateRuleValueDTO.getDay()*DayTypeEnum.YEAR.getNum();
}else{
day=calcuateRuleValueDTO.getDay();
}
LocalDate beforeDay=today.minusDays(day);
Long ruleId=calcuateRuleValueDTO.getRuleId();
//获取今日的值
DataQualityRuleDaily toDayQuality=new DataQualityRuleDaily();
toDayQuality.setDayStatisticValue(dayStatisValueDB);
//获取之前天数的值
DataQualityRuleDaily beforeQuality=dataQualityRuleDailyService.getByRuleIdAndDate(ruleId,beforeDay);
//计算波动率
BigDecimal statisValue=calculateVolatilityService.calculateVolatility(toDayQuality,beforeQuality);
ruleStatisticValueDto.setStatisticValue(statisValue);
ruleStatisticValueDto.setDayStatisticValuve(dayStatisValueDB);
}
//设置表的唯一率 空值率 重复值率 以及生成规则的excel数据
//获取模板ID,如果是以下几种模板,要计算规则所在表对应规则的比率
// 15:唯一值(固定) 19:空值(固定) 23:重复值(固定)
String dbName=calcuateRuleValueDTO.getDataQualityInfo().getDatabaseName();
String tableName=calcuateRuleValueDTO.getDataQualityInfo().getTableName();
String fieldName=calcuateRuleValueDTO.getFieldName();
Integer templateId=calcuateRuleValueDTO.getTemplateId();
TableStatisticValueDto tableStatisticValueDto=new TableStatisticValueDto();
tableStatisticValueDto.setConnectId(connectId);
tableStatisticValueDto.setDbName(dbName);
tableStatisticValueDto.setTableName(tableName);
tableStatisticValueDto.setFieldName(fieldName);
tableStatisticValueDto.setSqlWhere(calcuateRuleValueDTO.getSqlWhere());
tableStatisticValueDto.setPartitionFieldList(calcuateRuleValueDTO.getPartitionFieldList());
if(templateId!=null){
AbstractTableStatisticStrategy tableStatisticStrategy=TableStatisticStrategyFactory.getServiceByType(templateId);
if(tableStatisticStrategy!=null){
TableStatisticValueVO tableStatisticValueVO= tableStatisticStrategy.calculateTableStatisticValue(tableStatisticValueDto);
ruleStatisticValueDto.setTableRuleRate(tableStatisticValueVO.getTableRuleRate());
ruleStatisticValueDto.setTableRuleRow(tableStatisticValueVO.getTableRuleRow());
ruleStatisticValueDto.setTableTotalRow(tableStatisticValueVO.getTableTotalRow());
//获取规则行数据
List<RuleDataRowVO> rowList=tableStatisticValueVO.getRowList();
//保存每日报表数据
saveExcelDailyData(rowList,calcuateRuleValueDTO.getQualityInfoId(),calcuateRuleValueDTO.getRuleId());
}
}
} catch (Exception e) {
e.printStackTrace();
}
return ruleStatisticValueDto;
}
/**
* @Description
* @Author chengweiping
* @Date 2020/10/20 16:17
*/
private void saveExcelDailyData(List<RuleDataRowVO> rowList, Long qualityInfoId,Long ruleId){
if(CollectionUtil.isEmpty(rowList)){
return;
}
try{
LocalDateTime nowDateTime= LocalDateTime.now();
LocalDate nowDate=LocalDate.now();
Map<String, Object> map=new HashMap<>();
map.put("quality_info_id",qualityInfoId);
map.put("rule_id",ruleId);
map.put("statistic_date",nowDate);
dataQualityExcelDailyService.removeByMap(map);
List<DataQualityExcelDaily> resultList=rowList.stream().map(e->{
DataQualityExcelDaily dataQualityExcelDaily=new DataQualityExcelDaily();
dataQualityExcelDaily.setQualityInfoId(qualityInfoId);
dataQualityExcelDaily.setRuleId(ruleId);
dataQualityExcelDaily.setCreateTime(nowDateTime);
dataQualityExcelDaily.setTableData(e.getTableData());
dataQualityExcelDaily.setTableField(e.getTableField());
dataQualityExcelDaily.setStatisticDate(nowDate);
return dataQualityExcelDaily;
}).collect(Collectors.toList());
int totalPage = PageUtil.totalPage(resultList.size(), 100);
for(int i=0;i<totalPage;i++){
List subList=CollUtil.sub(resultList,i*100,(i+1)*100);
dataQualityExcelDailyService.saveBatch(subList,100);
}
}catch (Exception e){
e.printStackTrace();
}
}
/**
* @Description 校验模板规则,(试执行sql)
* @Author chengweiping
* @Date 2020/10/12 23:20
*/
public final BigDecimal verfiyTempalteRule(CalcuateRuleValueDto calcuateRuleValueDTO) throws Exception{
Integer connectId=calcuateRuleValueDTO.getConnectId();
DataSourceStrategy dataSourceStrategy=dataQualityRuleService.getDataSourceStrategyByConnectId(connectId);
BigDecimal dayStatisValueDB=null;
try {
Long ruleId=calcuateRuleValueDTO.getRuleId();
QueryWrapper queryWrapper=new QueryWrapper();
queryWrapper.eq("rule_id",ruleId);
List<DataQualityRulePartitionField> partitionFieldList= dataQualityRulePartitionFieldService.list(queryWrapper);
calcuateRuleValueDTO.setPartitionFieldList(partitionFieldList);
//获取今天规则的统计值
dayStatisValueDB=getTodayDayStatisValue(calcuateRuleValueDTO,dataSourceStrategy);
} catch (Exception e) {
e.printStackTrace();
throw e;
}
return dayStatisValueDB;
}
/**
* @Description 获取今天的统计值,每种规则的实现不一样,由子类实现
* @Author chengweiping
* @Date 2020/10/14 14:43
*/
public abstract BigDecimal getTodayDayStatisValue(CalcuateRuleValueDto calcuateRuleValueDTO, DataSourceStrategy dataSourceStrategy) throws Exception;
}
策略工厂类:
RuleModelTypeFactory.java
package cn.getech.data.manager.service.factory;
import cn.getech.data.manager.service.strategy.AbstractCalcuateRuleValueStrategy;
import java.util.concurrent.ConcurrentHashMap;
/**
* @ClassName DataSourceStrategyFactory
* @Description 表明服务工厂
* @Author Getech
* @Date 2020/10/10 14:06
*/
public class RuleModelTypeFactory {
private static ConcurrentHashMap<Integer, AbstractCalcuateRuleValueStrategy> serviceMap=new ConcurrentHashMap<>();
public static AbstractCalcuateRuleValueStrategy getServiceByType(Integer ruleModel){
return serviceMap.get(ruleModel);
}
public static void setService(Integer ruleModel, AbstractCalcuateRuleValueStrategy strategy){
serviceMap.put(ruleModel, strategy);
}
}
枚举类:
RuleModelTypeEnum.java
package cn.getech.data.manager.constant;
/**
* @ClassName DataSourceTypeEnum
* @Description TODO
* @Author Getech
* @Date 2020/10/10 14:22
*/
public enum RuleModelTypeEnum {
/**
* 1:表行数 2:表大小 3:字段平均值 4:字段汇总值 5:字段最大值
* 6 字段最小值 7: 字段唯一值 8: 字段空值 9:字段重复值
*/
TABLE_ROW(1,"表行数"),
TABLE_SIZE(2,"表大小"),
FIELD_AVG(3,"字段平均值"),
FIELD_SUM(4,"字段汇总值"),
FIELD_MAX(5,"字段最大值"),
FIELD_MIN(6,"字段最小值"),
FIELD_UNIQUE(7,"字段唯一值"),
FIELD_NULL(8,"字段空值"),
FIELD_REPEAT(9,"字段重复值"),
LIB_TEMPLATE(100,"模板库规则自定义类型");
private Integer ruleModel;
private String name;
RuleModelTypeEnum(Integer ruleModel, String name) {
this.ruleModel = ruleModel;
this.name = name;
}
public Integer getRuleModel() {
return ruleModel;
}
public void setRuleModel(Integer ruleModel) {
this.ruleModel = ruleModel;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}}
具体策略实现类:
FieldAvgStrategy.java
package cn.getech.data.manager.service.strategy.impl;
import cn.getech.data.manager.constant.RuleModelTypeEnum;
import cn.getech.data.manager.model.dto.CalcuateRuleValueDto;
import cn.getech.data.manager.model.dto.QueryDto;
import cn.getech.data.manager.model.dto.RuleStatisticValueDto;
import cn.getech.data.manager.service.IDataQualityRuleService;
import cn.getech.data.manager.service.factory.RuleModelTypeFactory;
import cn.getech.data.manager.service.strategy.AbstractCalcuateRuleValueStrategy;
import cn.getech.data.manager.service.strategy.DataSourceStrategy;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/**
* @ClassName TableRowStrategyAbstract
* @Description 字段平均值策略
* @Author Getech
* @Date 2020/10/12 23:32
*/
@Service
public class FieldAvgStrategy extends AbstractCalcuateRuleValueStrategy implements InitializingBean {
@Autowired
private IDataQualityRuleService dataQualityRuleService;
@Override
public void afterPropertiesSet() throws Exception {
RuleModelTypeFactory.setService(RuleModelTypeEnum.FIELD_AVG.getRuleModel(),this);
}
@Override
public BigDecimal getTodayDayStatisValue(CalcuateRuleValueDto calcuateRuleValueDTO, DataSourceStrategy dataSourceStrategy) throws Exception {
Integer connectId=calcuateRuleValueDTO.getDataQualityInfo().getConnectId();
RuleStatisticValueDto ruleStatisticValueDto=new RuleStatisticValueDto();
BigDecimal bd=null;
try {
String dbName=calcuateRuleValueDTO.getDataQualityInfo().getDatabaseName();
String tableName=calcuateRuleValueDTO.getDataQualityInfo().getTableName();
String fieldName=calcuateRuleValueDTO.getFieldName();
QueryDto queryDto=new QueryDto();
queryDto.setConnectId(connectId);
queryDto.setDbName(dbName);
queryDto.setTableName(tableName);
queryDto.setFieldName(fieldName);
queryDto.setSqlWhere(calcuateRuleValueDTO.getSqlWhere());
queryDto.setPartitionFieldList(calcuateRuleValueDTO.getPartitionFieldList());
bd = dataSourceStrategy.getFieldAvgNum(queryDto);
ruleStatisticValueDto.setStatisticValue(bd);
ruleStatisticValueDto.setDayStatisticValuve(bd);
} catch (Exception e) {
e.printStackTrace();
throw e;
}
return bd;
}
}