This commit is contained in:
Jane
2023-12-22 10:59:10 +08:00
parent 751c43e199
commit d1ede2d4aa
2774 changed files with 291509 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>data-quality-service-parent</artifactId>
<groupId>com.platform</groupId>
<version>0.4.x</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<version>0.4.x</version>
<artifactId>data-quality-service-api</artifactId>
<dependencies>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-micro-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
<!--feign 依赖-->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.platform</groupId>
<artifactId>common-core</artifactId>
<version>0.4.x</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,19 @@
package cn.datax.service.data.quality.api.dto;
import lombok.Data;
import java.io.Serializable;
/**
* 准确性
*/
@Data
public class Accuracy implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 最大长度
*/
private Integer maxLength;
}

View File

@@ -0,0 +1,64 @@
package cn.datax.service.data.quality.api.dto;
import cn.datax.common.validate.ValidationGroups;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* <p>
* 核查规则信息表 实体DTO
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@ApiModel(value = "核查规则信息表Model")
@Data
public class CheckRuleDto implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "主键ID")
@NotBlank(message = "主键ID不能为空", groups = {ValidationGroups.Update.class})
private String id;
@ApiModelProperty(value = "规则名称")
private String ruleName;
@ApiModelProperty(value = "规则类型")
private String ruleTypeId;
@ApiModelProperty(value = "核查类型")
private String ruleItemId;
@ApiModelProperty(value = "规则级别3高、2中、1低")
private String ruleLevelId;
@ApiModelProperty(value = "数据源类型")
private String ruleDbType;
@ApiModelProperty(value = "数据源主键")
private String ruleSourceId;
@ApiModelProperty(value = "数据源")
private String ruleSource;
@ApiModelProperty(value = "数据表主键")
private String ruleTableId;
@ApiModelProperty(value = "数据表")
private String ruleTable;
@ApiModelProperty(value = "数据表名称")
private String ruleTableComment;
@ApiModelProperty(value = "核查字段主键")
private String ruleColumnId;
@ApiModelProperty(value = "核查字段")
private String ruleColumn;
@ApiModelProperty(value = "核查字段名称")
private String ruleColumnComment;
@ApiModelProperty(value = "核查配置")
@Valid
private RuleConfig ruleConfig;
@ApiModelProperty(value = "状态")
@NotNull(message = "状态不能为空", groups = {ValidationGroups.Insert.class, ValidationGroups.Update.class})
private String status;
@ApiModelProperty(value = "备注")
private String remark;
}

View File

@@ -0,0 +1,19 @@
package cn.datax.service.data.quality.api.dto;
import lombok.Data;
import java.io.Serializable;
/**
* 一致性
*/
@Data
public class Consistent implements Serializable {
private static final long serialVersionUID = 1L;
private String gbTypeId;
private String gbTypeCode;
private String gbTypeName;
private String bindGbColumn;
}

View File

@@ -0,0 +1,21 @@
package cn.datax.service.data.quality.api.dto;
import lombok.Data;
import java.io.Serializable;
/**
* 关联性
*/
@Data
public class Relevance implements Serializable {
private static final long serialVersionUID = 1L;
private String relatedTableId;
private String relatedTable;
private String relatedTableComment;
private String relatedColumnId;
private String relatedColumn;
private String relatedColumnComment;
}

View File

@@ -0,0 +1,35 @@
package cn.datax.service.data.quality.api.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
public class RuleConfig implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "核查类型编码")
private String ruleItemCode;
/**
* 一致性
*/
private Consistent consistent;
/**
* 关联性
*/
private Relevance relevance;
/**
* 及时性
*/
private Timeliness timeliness;
/**
* 准确性
*/
private Accuracy accuracy;
}

View File

@@ -0,0 +1,41 @@
package cn.datax.service.data.quality.api.dto;
import cn.datax.common.validate.ValidationGroups;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 数据质量监控任务日志信息表 实体DTO
* </p>
*
* @author AllDataDC
* @date 2022-11-13
*/
@ApiModel(value = "数据质量监控任务日志信息表Model")
@Data
public class ScheduleLogDto implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "主键ID")
@NotBlank(message = "主键ID不能为空", groups = {ValidationGroups.Update.class})
private String id;
@ApiModelProperty(value = "状态1成功 0失败")
private String status;
@ApiModelProperty(value = "执行任务主键")
private String executeJobId;
@ApiModelProperty(value = "执行规则主键")
private String executeRuleId;
@ApiModelProperty(value = "执行时间")
private LocalDateTime executeDate;
@ApiModelProperty(value = "执行结果")
private String executeResult;
@ApiModelProperty(value = "执行批次号")
private String executeBatch;
}

View File

@@ -0,0 +1,19 @@
package cn.datax.service.data.quality.api.dto;
import lombok.Data;
import java.io.Serializable;
/**
* 及时性
*/
@Data
public class Timeliness implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 判定阀值 当前时间-业务时间>阀值
*/
private Integer threshold;
}

View File

@@ -0,0 +1,93 @@
package cn.datax.service.data.quality.api.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* <p>
* 核查报告信息表
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Data
@Accessors(chain = true)
@TableName(value = "quality_check_report", autoResultMap = true)
public class CheckReportEntity implements Serializable {
private static final long serialVersionUID=1L;
/**
* 主键
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* 核查规则主键
*/
private String checkRuleId;
/**
* 核查时间
*/
private LocalDateTime checkDate;
/**
* 核查结果
*/
private String checkResult;
/**
* 核查数量
*/
private Integer checkTotalCount;
/**
* 不合规数量
*/
private Integer checkErrorCount;
/**
* 核查批次号
*/
private String checkBatch;
/**
* 规则名称
*/
@TableField(exist = false)
private String ruleName;
/**
* 规则类型
*/
@TableField(exist = false)
private String ruleType;
/**
* 数据源
*/
@TableField(exist = false)
private String ruleSource;
/**
* 数据表
*/
@TableField(exist = false)
private String ruleTable;
/**
* 核查字段
*/
@TableField(exist = false)
private String ruleColumn;
}

View File

@@ -0,0 +1,117 @@
package cn.datax.service.data.quality.api.entity;
import cn.datax.common.base.DataScopeBaseEntity;
import cn.datax.service.data.quality.api.dto.RuleConfig;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* <p>
* 核查规则信息表
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName(value = "quality_check_rule", autoResultMap = true)
public class CheckRuleEntity extends DataScopeBaseEntity {
private static final long serialVersionUID=1L;
/**
* 规则名称
*/
private String ruleName;
/**
* 规则类型主键
*/
private String ruleTypeId;
/**
* 核查类型主键
*/
private String ruleItemId;
/**
* 规则类型
*/
@TableField(exist = false)
private String ruleType;
/**
* 规则级别3高、2中、1低
*/
private String ruleLevelId;
@TableField(exist = false)
private String ruleLevel;
/**
* 数据源类型
*/
private String ruleDbType;
/**
* 数据源主键
*/
private String ruleSourceId;
/**
* 数据源
*/
private String ruleSource;
/**
* 数据表主键
*/
private String ruleTableId;
/**
* 数据表
*/
private String ruleTable;
/**
* 数据表名称
*/
private String ruleTableComment;
/**
* 核查字段主键
*/
private String ruleColumnId;
/**
* 核查字段
*/
private String ruleColumn;
/**
* 核查字段名称
*/
private String ruleColumnComment;
/**
* 核查配置
*/
@TableField(value = "config_json", typeHandler = JacksonTypeHandler.class)
private RuleConfig ruleConfig;
/**
* 核查脚本
*/
private String ruleSql;
/**
* 最近核查批次号(关联确定唯一核查报告)
*/
private String lastCheckBatch;
}

View File

@@ -0,0 +1,28 @@
package cn.datax.service.data.quality.api.entity;
import lombok.Data;
import java.io.Serializable;
@Data
public class DataReportEntity implements Serializable {
private static final long serialVersionUID=1L;
private String ruleTypeId;
private String ruleTypeName;
private String ruleId;
private String ruleName;
private String ruleSourceId;
private String ruleSourceName;
private String ruleLevelId;
private String ruleLevelName;
private Integer checkErrorCount;
private String ruleTypeCode;
private String ruleTableName;
private String ruleTableComment;
private String ruleColumnName;
private String ruleColumnComment;
private Integer checkTotalCount;
}

View File

@@ -0,0 +1,46 @@
package cn.datax.service.data.quality.api.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* <p>
* 规则核查类型信息表
* </p>
*
* @author AllDataDC
* @date 2022-11-15
*/
@Data
@Accessors(chain = true)
@TableName("quality_rule_item")
public class RuleItemEntity implements Serializable {
private static final long serialVersionUID=1L;
/**
* 主键
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* 规则类型
*/
private String ruleTypeId;
/**
* 核查类型编码
*/
private String itemCode;
/**
* 核查类型解释
*/
private String itemExplain;
}

View File

@@ -0,0 +1,41 @@
package cn.datax.service.data.quality.api.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* <p>
* 规则级别信息表
* </p>
*
* @author AllDataDC
* @date 2022-11-14
*/
@Data
@Accessors(chain = true)
@TableName("quality_rule_level")
public class RuleLevelEntity implements Serializable {
private static final long serialVersionUID=1L;
/**
* 主键
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* 规则级别编码
*/
private String code;
/**
* 规则级别名称
*/
private String name;
}

View File

@@ -0,0 +1,41 @@
package cn.datax.service.data.quality.api.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* <p>
* 规则类型信息表
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Data
@Accessors(chain = true)
@TableName("quality_rule_type")
public class RuleTypeEntity implements Serializable {
private static final long serialVersionUID=1L;
/**
* 主键
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* 类型名称
*/
private String name;
/**
* 类型编码
*/
private String code;
}

View File

@@ -0,0 +1,14 @@
package cn.datax.service.data.quality.api.entity;
import lombok.Data;
@Data
public class RuleTypeReportEntity extends RuleTypeEntity {
private static final long serialVersionUID=1L;
/**
* 不合规数量
*/
private Integer checkErrorCount;
}

View File

@@ -0,0 +1,61 @@
package cn.datax.service.data.quality.api.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* <p>
* 数据质量监控任务信息表
* </p>
*
* @author AllDataDC
* @date 2022-11-29
*/
@Data
@Accessors(chain = true)
@TableName("quality_schedule_job")
public class ScheduleJobEntity implements Serializable {
private static final long serialVersionUID=1L;
/**
* 主键
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* 任务名称
*/
private String jobName;
/**
* bean名称
*/
private String beanName;
/**
* 方法名称
*/
private String methodName;
/**
* 方法参数
*/
private String methodParams;
/**
* cron表达式
*/
private String cronExpression;
/**
* 状态1运行 0暂停
*/
private String status;
}

View File

@@ -0,0 +1,72 @@
package cn.datax.service.data.quality.api.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* <p>
* 数据质量监控任务日志信息表
* </p>
*
* @author AllDataDC
* @date 2022-11-13
*/
@Data
@Accessors(chain = true)
@TableName(value = "quality_schedule_log")
public class ScheduleLogEntity implements Serializable {
private static final long serialVersionUID=1L;
/**
* 主键
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* 状态1成功 0失败
*/
private String status;
/**
* 执行任务主键
*/
private String executeJobId;
@TableField(exist = false)
private String executeJobName;
/**
* 执行规则主键
*/
private String executeRuleId;
@TableField(exist = false)
private String executeRuleName;
@TableField(exist = false)
private String executeRuleTypeName;
/**
* 执行时间
*/
private LocalDateTime executeDate;
/**
* 执行结果
*/
private String executeResult;
/**
* 执行批次号
*/
private String executeBatch;
}

View File

@@ -0,0 +1,33 @@
package cn.datax.service.data.quality.api.enums;
public enum RuleItem {
Unique("unique_key", "验证用户指定的字段是否具有唯一性"),
AccuracyLength("accuracy_key_length", "验证长度是否符合规定"),
Integrity("integrity_key", "验证表中必须出现的字段非空"),
Relevance("relevance_key", "验证关联性"),
Timeliness("timeliness_key", "验证及时性"),
Consistent("consistent_key", "验证用户指定的字段枚举值是否合乎要求");
private final String code;
private final String desc;
RuleItem(String code, String desc) {
this.code = code;
this.desc = desc;
}
public String getCode() {
return code;
}
public static RuleItem getRuleItem(String code) {
for (RuleItem item : RuleItem.values()) {
if (item.code.equals(code)) {
return item;
}
}
return null;
}
}

View File

@@ -0,0 +1,15 @@
package cn.datax.service.data.quality.api.feign;
import cn.datax.service.data.quality.api.entity.CheckRuleEntity;
import cn.datax.service.data.quality.api.feign.factory.QualityServiceFeignFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(contextId = "qualityServiceFeign", value = "service-data-quality", fallbackFactory = QualityServiceFeignFallbackFactory.class)
public interface QualityServiceFeign {
@GetMapping("/checkRules/source/{sourceId}")
CheckRuleEntity getBySourceId(@PathVariable String sourceId);
}

View File

@@ -0,0 +1,17 @@
package cn.datax.service.data.quality.api.feign.factory;
import cn.datax.service.data.quality.api.feign.QualityServiceFeign;
import cn.datax.service.data.quality.api.feign.fallback.QualityServiceFeignFallbackImpl;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
@Component
public class QualityServiceFeignFallbackFactory implements FallbackFactory<QualityServiceFeign> {
@Override
public QualityServiceFeign create(Throwable throwable) {
QualityServiceFeignFallbackImpl feignFallback = new QualityServiceFeignFallbackImpl();
feignFallback.setCause(throwable);
return feignFallback;
}
}

View File

@@ -0,0 +1,22 @@
package cn.datax.service.data.quality.api.feign.fallback;
import cn.datax.service.data.quality.api.entity.CheckRuleEntity;
import cn.datax.service.data.quality.api.feign.QualityServiceFeign;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class QualityServiceFeignFallbackImpl implements QualityServiceFeign {
@Setter
private Throwable cause;
@Override
public CheckRuleEntity getBySourceId(String sourceId) {
log.error("feign 调用数据质量管理查询出错", cause);
throw new RuntimeException("feign 调用数据质量管理查询出错", cause);
}
}

View File

@@ -0,0 +1,31 @@
package cn.datax.service.data.quality.api.query;
import cn.datax.common.base.BaseQueryParams;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
/**
* <p>
* 核查报告信息表 查询实体
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CheckReportQuery extends BaseQueryParams {
private static final long serialVersionUID=1L;
private String ruleTypeId;
private String ruleName;
private String ruleSource;
private String ruleTable;
private String ruleColumn;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate checkDate;
}

View File

@@ -0,0 +1,26 @@
package cn.datax.service.data.quality.api.query;
import cn.datax.common.base.BaseQueryParams;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 核查规则信息表 查询实体
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class CheckRuleQuery extends BaseQueryParams {
private static final long serialVersionUID=1L;
private String ruleTypeId;
private String ruleName;
private String ruleSource;
private String ruleTable;
private String ruleColumn;
}

View File

@@ -0,0 +1,22 @@
package cn.datax.service.data.quality.api.query;
import cn.datax.common.base.BaseQueryParams;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 规则核查项信息表 查询实体
* </p>
*
* @author AllDataDC
* @date 2022-11-15
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class RuleItemQuery extends BaseQueryParams {
private static final long serialVersionUID=1L;
private String ruleTypeId;
}

View File

@@ -0,0 +1,20 @@
package cn.datax.service.data.quality.api.query;
import cn.datax.common.base.BaseQueryParams;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 规则级别信息表 查询实体
* </p>
*
* @author AllDataDC
* @date 2022-11-14
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class RuleLevelQuery extends BaseQueryParams {
private static final long serialVersionUID=1L;
}

View File

@@ -0,0 +1,22 @@
package cn.datax.service.data.quality.api.query;
import cn.datax.common.base.BaseQueryParams;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 规则类型信息表 查询实体
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class RuleTypeQuery extends BaseQueryParams {
private static final long serialVersionUID=1L;
private String name;
}

View File

@@ -0,0 +1,20 @@
package cn.datax.service.data.quality.api.query;
import cn.datax.common.base.BaseQueryParams;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 数据质量监控任务信息表 查询实体
* </p>
*
* @author AllDataDC
* @date 2022-11-29
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class ScheduleJobQuery extends BaseQueryParams {
private static final long serialVersionUID=1L;
}

View File

@@ -0,0 +1,23 @@
package cn.datax.service.data.quality.api.query;
import cn.datax.common.base.BaseQueryParams;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 数据质量监控任务日志信息表 查询实体
* </p>
*
* @author AllDataDC
* @date 2022-11-13
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class ScheduleLogQuery extends BaseQueryParams {
private static final long serialVersionUID=1L;
private String executeJobId;
private String ruleTypeId;
}

View File

@@ -0,0 +1,34 @@
package cn.datax.service.data.quality.api.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 核查报告信息表 实体VO
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Data
public class CheckReportVo implements Serializable {
private static final long serialVersionUID=1L;
private String id;
private String checkRuleId;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime checkDate;
private String checkResult;
private Integer checkTotalCount;
private Integer checkErrorCount;
private String ruleName;
private String ruleType;
private String ruleSource;
private String ruleTable;
private String ruleColumn;
}

View File

@@ -0,0 +1,44 @@
package cn.datax.service.data.quality.api.vo;
import cn.datax.service.data.quality.api.dto.RuleConfig;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 核查规则信息表 实体VO
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Data
public class CheckRuleVo implements Serializable {
private static final long serialVersionUID=1L;
private String id;
private String status;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime createTime;
private String remark;
private String ruleName;
private String ruleTypeId;
private String ruleItemId;
private String ruleType;
private String ruleLevelId;
private String ruleLevel;
private String ruleDbType;
private String ruleSourceId;
private String ruleSource;
private String ruleTableId;
private String ruleTable;
private String ruleTableComment;
private String ruleColumnId;
private String ruleColumn;
private String ruleColumnComment;
private RuleConfig ruleConfig;
}

View File

@@ -0,0 +1,24 @@
package cn.datax.service.data.quality.api.vo;
import lombok.Data;
import java.io.Serializable;
/**
* <p>
* 规则核查项信息表 实体VO
* </p>
*
* @author AllDataDC
* @date 2022-11-15
*/
@Data
public class RuleItemVo implements Serializable {
private static final long serialVersionUID=1L;
private String id;
private String ruleTypeId;
private String itemCode;
private String itemExplain;
}

View File

@@ -0,0 +1,23 @@
package cn.datax.service.data.quality.api.vo;
import lombok.Data;
import java.io.Serializable;
/**
* <p>
* 规则级别信息表 实体VO
* </p>
*
* @author AllDataDC
* @date 2022-11-14
*/
@Data
public class RuleLevelVo implements Serializable {
private static final long serialVersionUID=1L;
private String id;
private String code;
private String name;
}

View File

@@ -0,0 +1,23 @@
package cn.datax.service.data.quality.api.vo;
import lombok.Data;
import java.io.Serializable;
/**
* <p>
* 规则类型信息表 实体VO
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Data
public class RuleTypeVo implements Serializable {
private static final long serialVersionUID=1L;
private String id;
private String name;
private String code;
}

View File

@@ -0,0 +1,27 @@
package cn.datax.service.data.quality.api.vo;
import lombok.Data;
import java.io.Serializable;
/**
* <p>
* 数据质量监控任务信息表 实体VO
* </p>
*
* @author AllDataDC
* @date 2022-11-29
*/
@Data
public class ScheduleJobVo implements Serializable {
private static final long serialVersionUID=1L;
private String id;
private String status;
private String jobName;
private String beanName;
private String methodName;
private String methodParams;
private String cronExpression;
}

View File

@@ -0,0 +1,33 @@
package cn.datax.service.data.quality.api.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 数据质量监控任务日志信息表 实体VO
* </p>
*
* @author AllDataDC
* @date 2022-11-13
*/
@Data
public class ScheduleLogVo implements Serializable {
private static final long serialVersionUID=1L;
private String id;
private String status;
private String executeJobId;
private String executeRuleId;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime executeDate;
private String executeResult;
private String executeBatch;
private String executeJobName;
private String executeRuleName;
private String executeRuleTypeName;
}

View File

@@ -0,0 +1,3 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.datax.service.data.quality.api.feign.factory.QualityServiceFeignFallbackFactory,\
cn.datax.service.data.quality.api.feign.fallback.QualityServiceFeignFallbackImpl

View File

@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>data-quality-service-parent</artifactId>
<groupId>com.platform</groupId>
<version>0.4.x</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<version>0.4.x</version>
<artifactId>data-quality-service</artifactId>
<dependencies>
<!--web 模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!--配置中心客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.platform</groupId>
<artifactId>common-mybatis</artifactId>
<version>0.4.x</version>
</dependency>
<dependency>
<groupId>com.platform</groupId>
<artifactId>common-redis</artifactId>
<version>0.4.x</version>
</dependency>
<dependency>
<groupId>com.platform</groupId>
<artifactId>common-security</artifactId>
<version>0.4.x</version>
</dependency>
<dependency>
<groupId>com.platform</groupId>
<artifactId>common-log</artifactId>
<version>0.4.x</version>
</dependency>
<dependency>
<groupId>com.platform</groupId>
<artifactId>data-quality-service-api</artifactId>
<version>0.4.x</version>
</dependency>
<dependency>
<groupId>com.platform</groupId>
<artifactId>common-database</artifactId>
<version>0.4.x</version>
</dependency>
<dependency>
<groupId>com.platform</groupId>
<artifactId>data-metadata-service-api</artifactId>
<version>0.4.x</version>
</dependency>
<dependency>
<groupId>com.platform</groupId>
<artifactId>data-standard-service-api</artifactId>
<version>0.4.x</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,18 @@
package cn.datax.service.data.quality;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.scheduling.annotation.EnableAsync;
@EnableAsync
@EnableFeignClients(basePackages = {"cn.datax.service.system.api.feign", "cn.datax.service.data.metadata.api.feign"})
@SpringBootApplication
public class DataxQualityApplication {
public static void main(String[] args) {
SpringApplication.run(DataxQualityApplication.class);
}
}

View File

@@ -0,0 +1,78 @@
package cn.datax.service.data.quality.config;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.aop.DynamicDataSourceAnnotationAdvisor;
import com.baomidou.dynamic.datasource.aop.DynamicDataSourceAnnotationInterceptor;
import com.baomidou.dynamic.datasource.processor.DsProcessor;
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
import com.baomidou.dynamic.datasource.provider.YmlDynamicDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceCreatorAutoConfiguration;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid.DruidDynamicDataSourceConfiguration;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Role;
import javax.sql.DataSource;
import java.util.Map;
/**
* 动态数据源核心自动配置类
* @author AllDataDC
* @date 2023/03/17
*/
@Slf4j
@Configuration
@AllArgsConstructor
@EnableConfigurationProperties(DynamicDataSourceProperties.class)
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
@Import(value = {DruidDynamicDataSourceConfiguration.class, DynamicDataSourceCreatorAutoConfiguration.class})
@ConditionalOnProperty(prefix = DynamicDataSourceProperties.PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
public class DynamicDSConfiguration {
private final DynamicDataSourceProperties properties;
//读取多数据源配置注入到spring容器中
@Bean
@ConditionalOnMissingBean
public DynamicDataSourceProvider dynamicDataSourceProvider() {
Map<String, DataSourceProperty> datasourceMap = properties.getDatasource();
return new YmlDynamicDataSourceProvider(datasourceMap);
}
//注册自己的动态多数据源DataSource
@Bean
@ConditionalOnMissingBean
public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
dataSource.setPrimary(properties.getPrimary());
dataSource.setStrict(properties.getStrict());
dataSource.setStrategy(properties.getStrategy());
dataSource.setProvider(dynamicDataSourceProvider);
dataSource.setP6spy(properties.getP6spy());
dataSource.setSeata(properties.getSeata());
return dataSource;
}
//AOP切面对DS注解过的方法进行增强达到切换数据源的目的
@Role(value = BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
@ConditionalOnMissingBean
public DynamicDataSourceAnnotationAdvisor dynamicDatasourceAnnotationAdvisor(DsProcessor dsProcessor) {
DynamicDataSourceAnnotationInterceptor interceptor = new DynamicDataSourceAnnotationInterceptor(properties.isAllowedPublicOnly(), dsProcessor);
DynamicDataSourceAnnotationAdvisor advisor = new DynamicDataSourceAnnotationAdvisor(interceptor);
advisor.setOrder(properties.getOrder());
return advisor;
}
}

View File

@@ -0,0 +1,21 @@
package cn.datax.service.data.quality.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@Configuration
public class SchedulingConfig {
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
// 定时任务执行线程池核心线程数
taskScheduler.setPoolSize(5);
taskScheduler.setRemoveOnCancelPolicy(true);
taskScheduler.setThreadNamePrefix("TaskSchedulerThreadPool-");
taskScheduler.initialize();
return taskScheduler;
}
}

View File

@@ -0,0 +1,57 @@
package cn.datax.service.data.quality.config;
import cn.datax.common.core.DataConstant;
import cn.datax.service.data.quality.api.entity.ScheduleJobEntity;
import cn.datax.service.data.quality.service.ScheduleJobService;
import cn.datax.service.data.quality.schedule.CronTaskRegistrar;
import cn.datax.service.data.quality.schedule.SchedulingRunnable;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
@Slf4j
@Component
@RequiredArgsConstructor
public class StartedUpRunner implements ApplicationRunner {
private final ConfigurableApplicationContext context;
private final Environment environment;
@Autowired
private CronTaskRegistrar cronTaskRegistrar;
@Autowired
private ScheduleJobService scheduleJobService;
@Override
public void run(ApplicationArguments args) {
if (context.isActive()) {
String banner = "-----------------------------------------\n" +
"服务启动成功,时间:" + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()) + "\n" +
"服务名称:" + environment.getProperty("spring.application.name") + "\n" +
"端口号:" + environment.getProperty("server.port") + "\n" +
"-----------------------------------------";
System.out.println(banner);
List<ScheduleJobEntity> list = scheduleJobService.list(Wrappers.<ScheduleJobEntity>lambdaQuery().eq(ScheduleJobEntity::getStatus, DataConstant.TrueOrFalse.TRUE.getKey()));
if (CollUtil.isNotEmpty(list)) {
list.forEach(job -> {
SchedulingRunnable task = new SchedulingRunnable(job.getId(), job.getBeanName(), job.getMethodName(), job.getMethodParams());
cronTaskRegistrar.addCronTask(task, job.getCronExpression());
});
}
log.info("定时任务已加载完毕...");
}
}
}

View File

@@ -0,0 +1,117 @@
package cn.datax.service.data.quality.config;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.bind.annotation.RequestMethod;
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.builders.*;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
@Configuration
@ConditionalOnProperty(prefix = "swagger", name = "enable", havingValue = "true")
@EnableConfigurationProperties(SwaggerProperties.class)
@EnableSwagger2
@EnableKnife4j
@Import(BeanValidatorPluginsConfiguration.class)
public class SwaggerConfig {
@Autowired
private SwaggerProperties swaggerProperties;
/**
* 创建API应用
* apiInfo() 增加API相关信息
* 通过select()函数返回一个ApiSelectorBuilder实例,用来控制哪些接口暴露给Swagger来展现
* 本例采用指定扫描的包路径来定义指定要建立API的目录。
*
* @return
*/
@Bean
public Docket createRestApi(){
//版本类型是swagger2
return new Docket(DocumentationType.SWAGGER_2)
//通过调用自定义方法apiInfo获得文档的主要信息
.apiInfo(apiInfo())
//设置全局参数
.globalOperationParameters(globalParamBuilder())
//设置全局响应参数
.globalResponseMessage(RequestMethod.GET,responseBuilder())
.globalResponseMessage(RequestMethod.POST,responseBuilder())
.globalResponseMessage(RequestMethod.PUT,responseBuilder())
.globalResponseMessage(RequestMethod.DELETE,responseBuilder())
.select()
//扫描该包下面的API注解
.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
.paths(PathSelectors.any())
.build()
//设置安全认证
;
}
/**
* 创建该API的基本信息这些基本信息会展现在文档页面中
* 访问地址http://项目实际地址/swagger-ui.html
* @return
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(swaggerProperties.getTitle())
.description(swaggerProperties.getDescription())
.termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl())
.version(swaggerProperties.getVersion())
.contact(new Contact(swaggerProperties.getContact().getName(), swaggerProperties.getContact().getUrl(), swaggerProperties.getContact().getEmail()))
.build();
}
/**
* 安全认证参数
* @return
*/
private List<ApiKey> security() {
List<ApiKey> apiKeys = new ArrayList<>();
apiKeys.add(new ApiKey("Authorization", "Authorization", "header"));
return apiKeys;
}
/**
* 构建全局参数列表
* @return
*/
private List<Parameter> globalParamBuilder(){
List<Parameter> pars = new ArrayList<>();
pars.add(parameterBuilder("Authorization","令牌","string","header",false).build());
return pars;
}
/**
* 创建参数
* @return
*/
private ParameterBuilder parameterBuilder(String name, String desc, String type, String parameterType, boolean required) {
ParameterBuilder tokenPar = new ParameterBuilder();
tokenPar.name(name).description(desc).modelRef(new ModelRef(type)).parameterType(parameterType).required(required).build();
return tokenPar;
}
/**
* 创建全局响应值
* @return
*/
private List<ResponseMessage> responseBuilder() {
List<ResponseMessage> responseMessageList = new ArrayList<>();
responseMessageList.add(new ResponseMessageBuilder().code(200).message("响应成功").build());
responseMessageList.add(new ResponseMessageBuilder().code(500).message("服务器内部错误").build());
return responseMessageList;
}
}

View File

@@ -0,0 +1,101 @@
package cn.datax.service.data.quality.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(ignoreUnknownFields = false, prefix = "swagger")
public class SwaggerProperties {
private Boolean enable;
private String title;
private String description;
private String version;
private String termsOfServiceUrl;
private String basePackage;
private Contact contact;
public Boolean getEnable() {
return enable;
}
public void setEnable(Boolean enable) {
this.enable = enable;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getTermsOfServiceUrl() {
return termsOfServiceUrl;
}
public void setTermsOfServiceUrl(String termsOfServiceUrl) {
this.termsOfServiceUrl = termsOfServiceUrl;
}
public String getBasePackage() {
return basePackage;
}
public void setBasePackage(String basePackage) {
this.basePackage = basePackage;
}
public Contact getContact() {
return contact;
}
public void setContact(Contact contact) {
this.contact = contact;
}
public static class Contact {
private String name;
private String url;
private String email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
}

View File

@@ -0,0 +1,17 @@
package cn.datax.service.data.quality.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity(debug = false)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().anyRequest().permitAll().and().logout().permitAll();
}
}

View File

@@ -0,0 +1,112 @@
package cn.datax.service.data.quality.controller;
import cn.datax.common.core.JsonPage;
import cn.datax.common.core.R;
import cn.datax.service.data.quality.api.entity.CheckReportEntity;
import cn.datax.service.data.quality.api.entity.DataReportEntity;
import cn.datax.service.data.quality.api.vo.CheckReportVo;
import cn.datax.service.data.quality.api.query.CheckReportQuery;
import cn.datax.service.data.quality.mapstruct.CheckReportMapper;
import cn.datax.service.data.quality.service.CheckReportService;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import cn.datax.common.base.BaseController;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* <p>
* 核查报告信息表 前端控制器
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Api(tags = {"核查报告信息表"})
@RestController
@RequestMapping("/checkReports")
public class CheckReportController extends BaseController {
@Autowired
private CheckReportService checkReportService;
@Autowired
private CheckReportMapper checkReportMapper;
/**
* 通过ID查询信息
*
* @param id
* @return
*/
@ApiOperation(value = "获取详细信息", notes = "根据url的id来获取详细信息")
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
@GetMapping("/{id}")
public R getCheckReportById(@PathVariable String id) {
CheckReportEntity checkReportEntity = checkReportService.getCheckReportById(id);
return R.ok().setData(checkReportMapper.toVO(checkReportEntity));
}
/**
* 分页查询信息
*
* @param checkReportQuery
* @return
*/
@ApiOperation(value = "分页查询", notes = "")
@ApiImplicitParams({
@ApiImplicitParam(name = "checkReportQuery", value = "查询实体checkReportQuery", required = true, dataTypeClass = CheckReportQuery.class)
})
@GetMapping("/page")
public R getCheckReportPage(CheckReportQuery checkReportQuery) {
QueryWrapper<CheckReportEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(StrUtil.isNotBlank(checkReportQuery.getRuleTypeId()), "r.rule_type_id", checkReportQuery.getRuleTypeId());
queryWrapper.like(StrUtil.isNotBlank(checkReportQuery.getRuleName()), "r.rule_name", checkReportQuery.getRuleName());
queryWrapper.like(StrUtil.isNotBlank(checkReportQuery.getRuleSource()), "r.rule_source", checkReportQuery.getRuleSource());
queryWrapper.like(StrUtil.isNotBlank(checkReportQuery.getRuleTable()), "r.rule_table", checkReportQuery.getRuleTable());
queryWrapper.like(StrUtil.isNotBlank(checkReportQuery.getRuleColumn()), "r.rule_column", checkReportQuery.getRuleColumn());
// 确定唯一核查报告
queryWrapper.apply("c.check_batch = r.last_check_batch");
IPage<CheckReportEntity> page = checkReportService.page(new Page<>(checkReportQuery.getPageNum(), checkReportQuery.getPageSize()), queryWrapper);
List<CheckReportVo> collect = page.getRecords().stream().map(checkReportMapper::toVO).collect(Collectors.toList());
JsonPage<CheckReportVo> jsonPage = new JsonPage<>(page.getCurrent(), page.getSize(), page.getTotal(), collect);
return R.ok().setData(jsonPage);
}
@GetMapping("/getReportBySource")
public R getReportBySource(CheckReportQuery checkReportQuery) {
LocalDate checkDate = checkReportQuery.getCheckDate();
String date = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(checkDate);
List<DataReportEntity> list = checkReportService.getReportBySource(date);
return R.ok().setData(list);
}
@GetMapping("/getReportByType")
public R getReportByType(CheckReportQuery checkReportQuery) {
LocalDate checkDate = checkReportQuery.getCheckDate();
String date = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(checkDate);
List<DataReportEntity> list = checkReportService.getReportByType(date);
return R.ok().setData(list);
}
@GetMapping("/getReportDetail")
public R getReportDetail(CheckReportQuery checkReportQuery) {
LocalDate checkDate = checkReportQuery.getCheckDate();
String date = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(checkDate);
Map<String, Object> map = checkReportService.getReportDetail(date);
return R.ok().setData(map);
}
}

View File

@@ -0,0 +1,148 @@
package cn.datax.service.data.quality.controller;
import cn.datax.common.core.JsonPage;
import cn.datax.common.core.R;
import cn.datax.common.security.annotation.DataInner;
import cn.datax.common.validate.ValidationGroups;
import cn.datax.service.data.quality.api.dto.CheckRuleDto;
import cn.datax.service.data.quality.api.entity.CheckRuleEntity;
import cn.datax.service.data.quality.api.vo.CheckRuleVo;
import cn.datax.service.data.quality.api.query.CheckRuleQuery;
import cn.datax.service.data.quality.mapstruct.CheckRuleMapper;
import cn.datax.service.data.quality.service.CheckRuleService;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import cn.datax.common.base.BaseController;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 核查规则信息表 前端控制器
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Api(tags = {"核查规则信息表"})
@RestController
@RequestMapping("/checkRules")
public class CheckRuleController extends BaseController {
@Autowired
private CheckRuleService checkRuleService;
@Autowired
private CheckRuleMapper checkRuleMapper;
@DataInner
@GetMapping("/source/{sourceId}")
public CheckRuleEntity getBySourceId(@PathVariable String sourceId) {
return checkRuleService.getBySourceId(sourceId);
}
/**
* 通过ID查询信息
*
* @param id
* @return
*/
@ApiOperation(value = "获取详细信息", notes = "根据url的id来获取详细信息")
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
@GetMapping("/{id}")
public R getCheckRuleById(@PathVariable String id) {
CheckRuleEntity checkRuleEntity = checkRuleService.getCheckRuleById(id);
return R.ok().setData(checkRuleMapper.toVO(checkRuleEntity));
}
/**
* 分页查询信息
*
* @param checkRuleQuery
* @return
*/
@ApiOperation(value = "分页查询", notes = "")
@ApiImplicitParams({
@ApiImplicitParam(name = "checkRuleQuery", value = "查询实体checkRuleQuery", required = true, dataTypeClass = CheckRuleQuery.class)
})
@GetMapping("/page")
public R getCheckRulePage(CheckRuleQuery checkRuleQuery) {
QueryWrapper<CheckRuleEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(StrUtil.isNotBlank(checkRuleQuery.getRuleTypeId()), "r.rule_type_id", checkRuleQuery.getRuleTypeId());
queryWrapper.like(StrUtil.isNotBlank(checkRuleQuery.getRuleName()), "r.rule_name", checkRuleQuery.getRuleName());
queryWrapper.like(StrUtil.isNotBlank(checkRuleQuery.getRuleSource()), "r.rule_source", checkRuleQuery.getRuleSource());
queryWrapper.like(StrUtil.isNotBlank(checkRuleQuery.getRuleTable()), "r.rule_table", checkRuleQuery.getRuleTable());
queryWrapper.like(StrUtil.isNotBlank(checkRuleQuery.getRuleColumn()), "r.rule_column", checkRuleQuery.getRuleColumn());
IPage<CheckRuleEntity> page = checkRuleService.page(new Page<>(checkRuleQuery.getPageNum(), checkRuleQuery.getPageSize()), queryWrapper);
List<CheckRuleVo> collect = page.getRecords().stream().map(checkRuleMapper::toVO).collect(Collectors.toList());
JsonPage<CheckRuleVo> jsonPage = new JsonPage<>(page.getCurrent(), page.getSize(), page.getTotal(), collect);
return R.ok().setData(jsonPage);
}
/**
* 添加
* @param checkRule
* @return
*/
@ApiOperation(value = "添加信息", notes = "根据checkRule对象添加信息")
@ApiImplicitParam(name = "checkRule", value = "详细实体checkRule", required = true, dataType = "CheckRuleDto")
@PostMapping()
public R saveCheckRule(@RequestBody @Validated({ValidationGroups.Insert.class}) CheckRuleDto checkRule) {
CheckRuleEntity checkRuleEntity = checkRuleService.saveCheckRule(checkRule);
return R.ok().setData(checkRuleMapper.toVO(checkRuleEntity));
}
/**
* 修改
* @param checkRule
* @return
*/
@ApiOperation(value = "修改信息", notes = "根据url的id来指定修改对象并根据传过来的信息来修改详细信息")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path"),
@ApiImplicitParam(name = "checkRule", value = "详细实体checkRule", required = true, dataType = "CheckRuleDto")
})
@PutMapping("/{id}")
public R updateCheckRule(@PathVariable String id, @RequestBody @Validated({ValidationGroups.Update.class}) CheckRuleDto checkRule) {
CheckRuleEntity checkRuleEntity = checkRuleService.updateCheckRule(checkRule);
return R.ok().setData(checkRuleMapper.toVO(checkRuleEntity));
}
/**
* 删除
* @param id
* @return
*/
@ApiOperation(value = "删除", notes = "根据url的id来指定删除对象")
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
@DeleteMapping("/{id}")
public R deleteCheckRuleById(@PathVariable String id) {
checkRuleService.deleteCheckRuleById(id);
return R.ok();
}
/**
* 批量删除
* @param ids
* @return
*/
@ApiOperation(value = "批量删除", notes = "根据url的ids来批量删除对象")
@ApiImplicitParam(name = "ids", value = "ID集合", required = true, dataType = "List", paramType = "path")
@DeleteMapping("/batch/{ids}")
public R deleteCheckRuleBatch(@PathVariable List<String> ids) {
checkRuleService.deleteCheckRuleBatch(ids);
return R.ok();
}
}

View File

@@ -0,0 +1,88 @@
package cn.datax.service.data.quality.controller;
import cn.datax.common.core.JsonPage;
import cn.datax.common.core.R;
import cn.datax.service.data.quality.api.entity.RuleItemEntity;
import cn.datax.service.data.quality.api.vo.RuleItemVo;
import cn.datax.service.data.quality.api.query.RuleItemQuery;
import cn.datax.service.data.quality.mapstruct.RuleItemMapper;
import cn.datax.service.data.quality.service.RuleItemService;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import cn.datax.common.base.BaseController;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 规则核查项信息表 前端控制器
* </p>
*
* @author AllDataDC
* @date 2022-11-15
*/
@Api(tags = {"规则核查项信息表"})
@RestController
@RequestMapping("/ruleItems")
public class RuleItemController extends BaseController {
@Autowired
private RuleItemService ruleItemService;
@Autowired
private RuleItemMapper ruleItemMapper;
/**
* 通过ID查询信息
*
* @param id
* @return
*/
@ApiOperation(value = "获取详细信息", notes = "根据url的id来获取详细信息")
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
@GetMapping("/{id}")
public R getRuleItemById(@PathVariable String id) {
RuleItemEntity ruleItemEntity = ruleItemService.getRuleItemById(id);
return R.ok().setData(ruleItemMapper.toVO(ruleItemEntity));
}
@ApiOperation(value = "获取列表", notes = "")
@GetMapping("/list")
public R getRuleTypeList(RuleItemQuery ruleItemQuery) {
QueryWrapper<RuleItemEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(StrUtil.isNotBlank(ruleItemQuery.getRuleTypeId()), "rule_type_id", ruleItemQuery.getRuleTypeId());
List<RuleItemEntity> list = ruleItemService.list(queryWrapper);
return R.ok().setData(list);
}
/**
* 分页查询信息
*
* @param ruleItemQuery
* @return
*/
@ApiOperation(value = "分页查询", notes = "")
@ApiImplicitParams({
@ApiImplicitParam(name = "ruleItemQuery", value = "查询实体ruleItemQuery", required = true, dataTypeClass = RuleItemQuery.class)
})
@GetMapping("/page")
public R getRuleItemPage(RuleItemQuery ruleItemQuery) {
QueryWrapper<RuleItemEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(StrUtil.isNotBlank(ruleItemQuery.getRuleTypeId()), "rule_type_id", ruleItemQuery.getRuleTypeId());
IPage<RuleItemEntity> page = ruleItemService.page(new Page<>(ruleItemQuery.getPageNum(), ruleItemQuery.getPageSize()), queryWrapper);
List<RuleItemVo> collect = page.getRecords().stream().map(ruleItemMapper::toVO).collect(Collectors.toList());
JsonPage<RuleItemVo> jsonPage = new JsonPage<>(page.getCurrent(), page.getSize(), page.getTotal(), collect);
return R.ok().setData(jsonPage);
}
}

View File

@@ -0,0 +1,84 @@
package cn.datax.service.data.quality.controller;
import cn.datax.common.core.JsonPage;
import cn.datax.common.core.R;
import cn.datax.service.data.quality.api.entity.RuleLevelEntity;
import cn.datax.service.data.quality.api.vo.RuleLevelVo;
import cn.datax.service.data.quality.api.query.RuleLevelQuery;
import cn.datax.service.data.quality.mapstruct.RuleLevelMapper;
import cn.datax.service.data.quality.service.RuleLevelService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import cn.datax.common.base.BaseController;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 规则级别信息表 前端控制器
* </p>
*
* @author AllDataDC
* @date 2022-11-14
*/
@Api(tags = {"规则级别信息表"})
@RestController
@RequestMapping("/ruleLevels")
public class RuleLevelController extends BaseController {
@Autowired
private RuleLevelService ruleLevelService;
@Autowired
private RuleLevelMapper ruleLevelMapper;
/**
* 通过ID查询信息
*
* @param id
* @return
*/
@ApiOperation(value = "获取详细信息", notes = "根据url的id来获取详细信息")
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
@GetMapping("/{id}")
public R getRuleLevelById(@PathVariable String id) {
RuleLevelEntity ruleLevelEntity = ruleLevelService.getRuleLevelById(id);
return R.ok().setData(ruleLevelMapper.toVO(ruleLevelEntity));
}
@ApiOperation(value = "获取列表", notes = "")
@GetMapping("/list")
public R getRuleTypeList() {
List<RuleLevelEntity> list = ruleLevelService.list(Wrappers.emptyWrapper());
return R.ok().setData(list);
}
/**
* 分页查询信息
*
* @param ruleLevelQuery
* @return
*/
@ApiOperation(value = "分页查询", notes = "")
@ApiImplicitParams({
@ApiImplicitParam(name = "ruleLevelQuery", value = "查询实体ruleLevelQuery", required = true, dataTypeClass = RuleLevelQuery.class)
})
@GetMapping("/page")
public R getRuleLevelPage(RuleLevelQuery ruleLevelQuery) {
QueryWrapper<RuleLevelEntity> queryWrapper = new QueryWrapper<>();
IPage<RuleLevelEntity> page = ruleLevelService.page(new Page<>(ruleLevelQuery.getPageNum(), ruleLevelQuery.getPageSize()), queryWrapper);
List<RuleLevelVo> collect = page.getRecords().stream().map(ruleLevelMapper::toVO).collect(Collectors.toList());
JsonPage<RuleLevelVo> jsonPage = new JsonPage<>(page.getCurrent(), page.getSize(), page.getTotal(), collect);
return R.ok().setData(jsonPage);
}
}

View File

@@ -0,0 +1,94 @@
package cn.datax.service.data.quality.controller;
import cn.datax.common.core.JsonPage;
import cn.datax.common.core.R;
import cn.datax.service.data.quality.api.entity.RuleTypeEntity;
import cn.datax.service.data.quality.api.entity.RuleTypeReportEntity;
import cn.datax.service.data.quality.api.vo.RuleTypeVo;
import cn.datax.service.data.quality.api.query.RuleTypeQuery;
import cn.datax.service.data.quality.mapstruct.RuleTypeMapper;
import cn.datax.service.data.quality.service.RuleTypeService;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import cn.datax.common.base.BaseController;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 规则类型信息表 前端控制器
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Api(tags = {"规则类型信息表"})
@RestController
@RequestMapping("/ruleTypes")
public class RuleTypeController extends BaseController {
@Autowired
private RuleTypeService ruleTypeService;
@Autowired
private RuleTypeMapper ruleTypeMapper;
/**
* 通过ID查询信息
*
* @param id
* @return
*/
@ApiOperation(value = "获取详细信息", notes = "根据url的id来获取详细信息")
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
@GetMapping("/{id}")
public R getRuleTypeById(@PathVariable String id) {
RuleTypeEntity ruleTypeEntity = ruleTypeService.getRuleTypeById(id);
return R.ok().setData(ruleTypeMapper.toVO(ruleTypeEntity));
}
@ApiOperation(value = "获取列表", notes = "")
@GetMapping("/list")
public R getRuleTypeList() {
List<RuleTypeEntity> list = ruleTypeService.list(Wrappers.emptyWrapper());
return R.ok().setData(list);
}
@ApiOperation(value = "获取列表", notes = "")
@GetMapping("/report/list")
public R getRuleTypeListForReport() {
List<RuleTypeReportEntity> list = ruleTypeService.getRuleTypeListForReport();
return R.ok().setData(list);
}
/**
* 分页查询信息
*
* @param ruleTypeQuery
* @return
*/
@ApiOperation(value = "分页查询", notes = "")
@ApiImplicitParams({
@ApiImplicitParam(name = "ruleTypeQuery", value = "查询实体ruleTypeQuery", required = true, dataTypeClass = RuleTypeQuery.class)
})
@GetMapping("/page")
public R getRuleTypePage(RuleTypeQuery ruleTypeQuery) {
QueryWrapper<RuleTypeEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.like(StrUtil.isNotBlank(ruleTypeQuery.getName()), "name", ruleTypeQuery.getName());
IPage<RuleTypeEntity> page = ruleTypeService.page(new Page<>(ruleTypeQuery.getPageNum(), ruleTypeQuery.getPageSize()), queryWrapper);
List<RuleTypeVo> collect = page.getRecords().stream().map(ruleTypeMapper::toVO).collect(Collectors.toList());
JsonPage<RuleTypeVo> jsonPage = new JsonPage<>(page.getCurrent(), page.getSize(), page.getTotal(), collect);
return R.ok().setData(jsonPage);
}
}

View File

@@ -0,0 +1,115 @@
package cn.datax.service.data.quality.controller;
import cn.datax.common.core.JsonPage;
import cn.datax.common.core.R;
import cn.datax.service.data.quality.api.entity.ScheduleJobEntity;
import cn.datax.service.data.quality.api.vo.ScheduleJobVo;
import cn.datax.service.data.quality.api.query.ScheduleJobQuery;
import cn.datax.service.data.quality.mapstruct.ScheduleJobMapper;
import cn.datax.service.data.quality.service.ScheduleJobService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import cn.datax.common.base.BaseController;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 数据质量监控任务信息表 前端控制器
* </p>
*
* @author AllDataDC
* @date 2022-11-29
*/
@Api(tags = {"数据质量监控任务信息表"})
@RestController
@RequestMapping("/scheduleJobs")
public class ScheduleJobController extends BaseController {
@Autowired
private ScheduleJobService scheduleJobService;
@Autowired
private ScheduleJobMapper scheduleJobMapper;
/**
* 通过ID查询信息
*
* @param id
* @return
*/
@ApiOperation(value = "获取详细信息", notes = "根据url的id来获取详细信息")
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
@GetMapping("/{id}")
public R getScheduleJobById(@PathVariable String id) {
ScheduleJobEntity scheduleJobEntity = scheduleJobService.getScheduleJobById(id);
return R.ok().setData(scheduleJobMapper.toVO(scheduleJobEntity));
}
/**
* 分页查询信息
*
* @param scheduleJobQuery
* @return
*/
@ApiOperation(value = "分页查询", notes = "")
@ApiImplicitParams({
@ApiImplicitParam(name = "scheduleJobQuery", value = "查询实体scheduleJobQuery", required = true, dataTypeClass = ScheduleJobQuery.class)
})
@GetMapping("/page")
public R getScheduleJobPage(ScheduleJobQuery scheduleJobQuery) {
QueryWrapper<ScheduleJobEntity> queryWrapper = new QueryWrapper<>();
IPage<ScheduleJobEntity> page = scheduleJobService.page(new Page<>(scheduleJobQuery.getPageNum(), scheduleJobQuery.getPageSize()), queryWrapper.orderByDesc("id"));
List<ScheduleJobVo> collect = page.getRecords().stream().map(scheduleJobMapper::toVO).collect(Collectors.toList());
JsonPage<ScheduleJobVo> jsonPage = new JsonPage<>(page.getCurrent(), page.getSize(), page.getTotal(), collect);
return R.ok().setData(jsonPage);
}
/**
* 暂停任务
* @param id
* @return
*/
@ApiOperation(value = "暂停任务", notes = "根据url的id来暂停指定任务")
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
@PostMapping("/pause/{id}")
public R pauseScheduleJobById(@PathVariable("id") String id) {
scheduleJobService.pauseScheduleJobById(id);
return R.ok();
}
/**
* 恢复任务
* @param id
* @return
*/
@ApiOperation(value = "恢复任务", notes = "根据url的id来恢复指定任务")
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
@PostMapping("/resume/{id}")
public R resumeScheduleJobById(@PathVariable("id") String id) {
scheduleJobService.resumeScheduleJobById(id);
return R.ok();
}
/**
* 立即执行任务
* @param id
* @return
*/
@ApiOperation(value = "立即执行任务", notes = "根据url的id来执行指定任务")
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
@PostMapping("/run/{id}")
public R runScheduleJobById(@PathVariable("id") String id) {
scheduleJobService.runScheduleJobById(id);
return R.ok();
}
}

View File

@@ -0,0 +1,105 @@
package cn.datax.service.data.quality.controller;
import cn.datax.common.core.JsonPage;
import cn.datax.common.core.R;
import cn.datax.service.data.quality.api.entity.ScheduleLogEntity;
import cn.datax.service.data.quality.api.vo.ScheduleLogVo;
import cn.datax.service.data.quality.api.query.ScheduleLogQuery;
import cn.datax.service.data.quality.mapstruct.ScheduleLogMapper;
import cn.datax.service.data.quality.service.ScheduleLogService;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import cn.datax.common.base.BaseController;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 数据质量监控任务日志信息表 前端控制器
* </p>
*
* @author AllDataDC
* @date 2022-11-13
*/
@Api(tags = {"数据质量监控任务日志信息表"})
@RestController
@RequestMapping("/scheduleLogs")
public class ScheduleLogController extends BaseController {
@Autowired
private ScheduleLogService scheduleLogService;
@Autowired
private ScheduleLogMapper scheduleLogMapper;
/**
* 通过ID查询信息
*
* @param id
* @return
*/
@ApiOperation(value = "获取详细信息", notes = "根据url的id来获取详细信息")
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
@GetMapping("/{id}")
public R getScheduleLogById(@PathVariable String id) {
ScheduleLogEntity scheduleLogEntity = scheduleLogService.getScheduleLogById(id);
return R.ok().setData(scheduleLogMapper.toVO(scheduleLogEntity));
}
/**
* 分页查询信息
*
* @param scheduleLogQuery
* @return
*/
@ApiOperation(value = "分页查询", notes = "")
@ApiImplicitParams({
@ApiImplicitParam(name = "scheduleLogQuery", value = "查询实体scheduleLogQuery", required = true, dataTypeClass = ScheduleLogQuery.class)
})
@GetMapping("/page")
public R getScheduleLogPage(ScheduleLogQuery scheduleLogQuery) {
QueryWrapper<ScheduleLogEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(StrUtil.isNotBlank(scheduleLogQuery.getExecuteJobId()), "l.execute_job_id", scheduleLogQuery.getExecuteJobId());
queryWrapper.eq(StrUtil.isNotBlank(scheduleLogQuery.getRuleTypeId()), "t.id", scheduleLogQuery.getRuleTypeId());
IPage<ScheduleLogEntity> page = scheduleLogService.page(new Page<>(scheduleLogQuery.getPageNum(), scheduleLogQuery.getPageSize()), queryWrapper.orderByDesc("l.id"));
List<ScheduleLogVo> collect = page.getRecords().stream().map(scheduleLogMapper::toVO).collect(Collectors.toList());
JsonPage<ScheduleLogVo> jsonPage = new JsonPage<>(page.getCurrent(), page.getSize(), page.getTotal(), collect);
return R.ok().setData(jsonPage);
}
/**
* 删除
* @param id
* @return
*/
@ApiOperation(value = "删除", notes = "根据url的id来指定删除对象")
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
@DeleteMapping("/{id}")
public R deleteScheduleLogById(@PathVariable String id) {
scheduleLogService.deleteScheduleLogById(id);
return R.ok();
}
/**
* 批量删除
* @param ids
* @return
*/
@ApiOperation(value = "批量删除", notes = "根据url的ids来批量删除对象")
@ApiImplicitParam(name = "ids", value = "ID集合", required = true, dataType = "List", paramType = "path")
@DeleteMapping("/batch/{ids}")
public R deleteScheduleLogBatch(@PathVariable List<String> ids) {
scheduleLogService.deleteScheduleLogBatch(ids);
return R.ok();
}
}

View File

@@ -0,0 +1,33 @@
package cn.datax.service.data.quality.dao;
import cn.datax.common.base.BaseDao;
import cn.datax.service.data.quality.api.entity.CheckReportEntity;
import cn.datax.service.data.quality.api.entity.DataReportEntity;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
* 核查报告信息表 Mapper 接口
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Mapper
public interface CheckReportDao extends BaseDao<CheckReportEntity> {
@Override
<E extends IPage<CheckReportEntity>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<CheckReportEntity> queryWrapper);
List<DataReportEntity> getReportBySource(@Param("checkDate") String checkDate);
List<DataReportEntity> getReportByType(@Param("checkDate") String checkDate);
List<DataReportEntity> getReportDetail(@Param("checkDate") String checkDate);
}

View File

@@ -0,0 +1,33 @@
package cn.datax.service.data.quality.dao;
import cn.datax.common.base.BaseDao;
import cn.datax.service.data.quality.api.entity.CheckRuleEntity;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.io.Serializable;
import java.util.List;
/**
* <p>
* 核查规则信息表 Mapper 接口
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Mapper
public interface CheckRuleDao extends BaseDao<CheckRuleEntity> {
@Override
CheckRuleEntity selectById(Serializable id);
@Override
List<CheckRuleEntity> selectList(@Param(Constants.WRAPPER) Wrapper<CheckRuleEntity> queryWrapper);
@Override
<E extends IPage<CheckRuleEntity>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<CheckRuleEntity> queryWrapper);
}

View File

@@ -0,0 +1,18 @@
package cn.datax.service.data.quality.dao;
import cn.datax.common.base.BaseDao;
import cn.datax.service.data.quality.api.entity.RuleItemEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 规则核查项信息表 Mapper 接口
* </p>
*
* @author AllDataDC
* @date 2022-11-15
*/
@Mapper
public interface RuleItemDao extends BaseDao<RuleItemEntity> {
}

View File

@@ -0,0 +1,18 @@
package cn.datax.service.data.quality.dao;
import cn.datax.common.base.BaseDao;
import cn.datax.service.data.quality.api.entity.RuleLevelEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 规则级别信息表 Mapper 接口
* </p>
*
* @author AllDataDC
* @date 2022-11-14
*/
@Mapper
public interface RuleLevelDao extends BaseDao<RuleLevelEntity> {
}

View File

@@ -0,0 +1,22 @@
package cn.datax.service.data.quality.dao;
import cn.datax.common.base.BaseDao;
import cn.datax.service.data.quality.api.entity.RuleTypeEntity;
import cn.datax.service.data.quality.api.entity.RuleTypeReportEntity;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* <p>
* 规则类型信息表 Mapper 接口
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Mapper
public interface RuleTypeDao extends BaseDao<RuleTypeEntity> {
List<RuleTypeReportEntity> selectListForReport();
}

View File

@@ -0,0 +1,20 @@
package cn.datax.service.data.quality.dao;
import cn.datax.common.base.BaseDao;
import cn.datax.service.data.quality.api.entity.ScheduleJobEntity;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
/**
* <p>
* 数据质量监控任务信息表 Mapper 接口
* </p>
*
* @author AllDataDC
* @date 2022-11-29
*/
@Mapper
@Repository
public interface ScheduleJobDao extends BaseDao<ScheduleJobEntity> {
}

View File

@@ -0,0 +1,24 @@
package cn.datax.service.data.quality.dao;
import cn.datax.common.base.BaseDao;
import cn.datax.service.data.quality.api.entity.ScheduleLogEntity;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* <p>
* 数据质量监控任务日志信息表 Mapper 接口
* </p>
*
* @author AllDataDC
* @date 2022-11-13
*/
@Mapper
public interface ScheduleLogDao extends BaseDao<ScheduleLogEntity> {
@Override
<E extends IPage<ScheduleLogEntity>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<ScheduleLogEntity> queryWrapper);
}

View File

@@ -0,0 +1,33 @@
package cn.datax.service.data.quality.mapstruct;
import cn.datax.service.data.quality.api.entity.CheckReportEntity;
import cn.datax.service.data.quality.api.vo.CheckReportVo;
import org.mapstruct.Mapper;
import java.util.List;
/**
* <p>
* 核查报告信息表 Mapper 实体映射
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Mapper(componentModel = "spring")
public interface CheckReportMapper {
/**
* 将源对象转换为VO对象
* @param e
* @return D
*/
CheckReportVo toVO(CheckReportEntity e);
/**
* 将源对象集合转换为VO对象集合
* @param es
* @return List<D>
*/
List<CheckReportVo> toVO(List<CheckReportEntity> es);
}

View File

@@ -0,0 +1,20 @@
package cn.datax.service.data.quality.mapstruct;
import cn.datax.common.mapstruct.EntityMapper;
import cn.datax.service.data.quality.api.dto.CheckRuleDto;
import cn.datax.service.data.quality.api.entity.CheckRuleEntity;
import cn.datax.service.data.quality.api.vo.CheckRuleVo;
import org.mapstruct.Mapper;
/**
* <p>
* 核查规则信息表 Mapper 实体映射
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Mapper(componentModel = "spring")
public interface CheckRuleMapper extends EntityMapper<CheckRuleDto, CheckRuleEntity, CheckRuleVo> {
}

View File

@@ -0,0 +1,33 @@
package cn.datax.service.data.quality.mapstruct;
import cn.datax.service.data.quality.api.entity.RuleItemEntity;
import cn.datax.service.data.quality.api.vo.RuleItemVo;
import org.mapstruct.Mapper;
import java.util.List;
/**
* <p>
* 规则核查项信息表 Mapper 实体映射
* </p>
*
* @author AllDataDC
* @date 2022-11-15
*/
@Mapper(componentModel = "spring")
public interface RuleItemMapper {
/**
* 将源对象转换为VO对象
* @param e
* @return D
*/
RuleItemVo toVO(RuleItemEntity e);
/**
* 将源对象集合转换为VO对象集合
* @param es
* @return List<D>
*/
List<RuleItemVo> toVO(List<RuleItemEntity> es);
}

View File

@@ -0,0 +1,33 @@
package cn.datax.service.data.quality.mapstruct;
import cn.datax.service.data.quality.api.entity.RuleLevelEntity;
import cn.datax.service.data.quality.api.vo.RuleLevelVo;
import org.mapstruct.Mapper;
import java.util.List;
/**
* <p>
* 规则级别信息表 Mapper 实体映射
* </p>
*
* @author AllDataDC
* @date 2022-11-14
*/
@Mapper(componentModel = "spring")
public interface RuleLevelMapper {
/**
* 将源对象转换为VO对象
* @param e
* @return D
*/
RuleLevelVo toVO(RuleLevelEntity e);
/**
* 将源对象集合转换为VO对象集合
* @param es
* @return List<D>
*/
List<RuleLevelVo> toVO(List<RuleLevelEntity> es);
}

View File

@@ -0,0 +1,34 @@
package cn.datax.service.data.quality.mapstruct;
import cn.datax.service.data.quality.api.entity.RuleTypeEntity;
import cn.datax.service.data.quality.api.vo.RuleTypeVo;
import org.mapstruct.Mapper;
import java.util.List;
/**
* <p>
* 规则类型信息表 Mapper 实体映射
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Mapper(componentModel = "spring")
public interface RuleTypeMapper {
/**
* 将源对象转换为VO对象
* @param e
* @return D
*/
RuleTypeVo toVO(RuleTypeEntity e);
/**
* 将源对象集合转换为VO对象集合
* @param es
* @return List<D>
*/
List<RuleTypeVo> toVO(List<RuleTypeEntity> es);
}

View File

@@ -0,0 +1,33 @@
package cn.datax.service.data.quality.mapstruct;
import cn.datax.service.data.quality.api.entity.ScheduleJobEntity;
import cn.datax.service.data.quality.api.vo.ScheduleJobVo;
import org.mapstruct.Mapper;
import java.util.List;
/**
* <p>
* 数据质量监控任务信息表 Mapper 实体映射
* </p>
*
* @author AllDataDC
* @date 2022-11-29
*/
@Mapper(componentModel = "spring")
public interface ScheduleJobMapper {
/**
* 将源对象转换为VO对象
* @param e
* @return D
*/
ScheduleJobVo toVO(ScheduleJobEntity e);
/**
* 将源对象集合转换为VO对象集合
* @param es
* @return List<D>
*/
List<ScheduleJobVo> toVO(List<ScheduleJobEntity> es);
}

View File

@@ -0,0 +1,33 @@
package cn.datax.service.data.quality.mapstruct;
import cn.datax.service.data.quality.api.entity.ScheduleLogEntity;
import cn.datax.service.data.quality.api.vo.ScheduleLogVo;
import org.mapstruct.Mapper;
import java.util.List;
/**
* <p>
* 数据质量监控任务日志信息表 Mapper 实体映射
* </p>
*
* @author AllDataDC
* @date 2022-11-13
*/
@Mapper(componentModel = "spring")
public interface ScheduleLogMapper {
/**
* 将源对象转换为VO对象
* @param e
* @return D
*/
ScheduleLogVo toVO(ScheduleLogEntity e);
/**
* 将源对象集合转换为VO对象集合
* @param es
* @return List<D>
*/
List<ScheduleLogVo> toVO(List<ScheduleLogEntity> es);
}

View File

@@ -0,0 +1,19 @@
package cn.datax.service.data.quality.schedule;
import cn.datax.common.exception.DataException;
import cn.datax.service.data.quality.schedule.rules.RuleItem;
import cn.datax.service.data.quality.schedule.rules.RuleItemRegistry;
import java.util.Optional;
public class CheckRuleFactory {
private static final RuleItemRegistry RULE_ITEM_REGISTRY = new RuleItemRegistry();
public CheckRuleFactory() {
}
public static RuleItem getRuleItem(String code) {
return Optional.ofNullable(RULE_ITEM_REGISTRY.getRuleItem(code)).orElseThrow(() -> new DataException(String.format("%s not supported.", code)));
}
}

View File

@@ -0,0 +1,58 @@
package cn.datax.service.data.quality.schedule;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.config.CronTask;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component
public class CronTaskRegistrar implements DisposableBean {
private final Map<Runnable, ScheduledTask> scheduledTasks = new ConcurrentHashMap<>(8);
@Autowired
private TaskScheduler taskScheduler;
public TaskScheduler getScheduler() {
return this.taskScheduler;
}
public void addCronTask(Runnable task, String cronExpression) {
addCronTask(new CronTask(task, cronExpression));
}
public void addCronTask(CronTask cronTask) {
if (cronTask != null) {
Runnable task = cronTask.getRunnable();
if (this.scheduledTasks.containsKey(task)) {
removeCronTask(task);
}
this.scheduledTasks.put(task, scheduleCronTask(cronTask));
}
}
public void removeCronTask(Runnable task) {
ScheduledTask scheduledTask = this.scheduledTasks.remove(task);
if (scheduledTask != null) {
scheduledTask.cancel();
}
}
public ScheduledTask scheduleCronTask(CronTask cronTask) {
ScheduledTask scheduledTask = new ScheduledTask();
scheduledTask.future = this.taskScheduler.schedule(cronTask.getRunnable(), cronTask.getTrigger());
return scheduledTask;
}
@Override
public void destroy() {
for (ScheduledTask task : this.scheduledTasks.values()) {
task.cancel();
}
this.scheduledTasks.clear();
}
}

View File

@@ -0,0 +1,18 @@
package cn.datax.service.data.quality.schedule;
import java.util.concurrent.ScheduledFuture;
public final class ScheduledTask {
volatile ScheduledFuture<?> future;
/**
* 取消定时任务
*/
public void cancel() {
ScheduledFuture<?> future = this.future;
if (future != null) {
future.cancel(true);
}
}
}

View File

@@ -0,0 +1,87 @@
package cn.datax.service.data.quality.schedule;
import cn.datax.common.utils.SpringContextHolder;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@Slf4j
public class SchedulingRunnable implements Runnable {
private String id;
private String beanName;
private String methodName;
private String params;
public SchedulingRunnable(String id, String beanName, String methodName, String params) {
this.id = id;
this.beanName = beanName;
this.methodName = methodName;
this.params = params;
}
@Override
public void run() {
log.info("定时任务开始执行 - id{}bean{},方法:{},参数:{}", id, beanName, methodName, params);
long startTime = System.currentTimeMillis();
Map<String, Object> map = new HashMap<>();
map.put("id", id);
String batch;
try {
Object target = SpringContextHolder.getBean(beanName);
Method method = target.getClass().getDeclaredMethod(methodName, Map.class);
if (StrUtil.isNotEmpty(params)) {
map.putAll(new ObjectMapper().readValue(params, Map.class));
}
batch = DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN);
map.put("batch", batch);
ReflectionUtils.makeAccessible(method);
method.invoke(target, map);
} catch (Exception ex) {
log.error(String.format("定时任务执行异常 - id%sbean%s方法%s参数%s ", id, beanName, methodName, params), ex);
}
long times = System.currentTimeMillis() - startTime;
log.info("定时任务执行结束 - id{}bean{},方法:{},参数:{},耗时:{} 毫秒", id, beanName, methodName, params, times);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
SchedulingRunnable that = (SchedulingRunnable) o;
if (params == null) {
return id.equals(that.id) &&
beanName.equals(that.beanName) &&
methodName.equals(that.methodName) &&
that.params == null;
}
return id.equals(that.id) &&
beanName.equals(that.beanName) &&
methodName.equals(that.methodName) &&
params.equals(that.params);
}
@Override
public int hashCode() {
if (params == null) {
return Objects.hash(id, beanName, methodName);
}
return Objects.hash(id, beanName, methodName, params);
}
}

View File

@@ -0,0 +1,27 @@
package cn.datax.service.data.quality.schedule.rules;
import cn.datax.common.database.constants.DbType;
import java.util.Map;
/**
* 准确性核查
* 核查项:最大长度
* select sum(case when length(column) > 15 then 1 else 0 end), count(*) from table;
*/
public class AccuracyLengthRule implements RuleItem {
private static String MAX_LENGTH = "max_length";
@Override
public String parse(DbType dbType, String table, String column, Map<String, Object> map) {
final StringBuilder builder = new StringBuilder();
builder.append("SELECT SUM(CASE WHEN LENGTH(").append(column).append(") > ").append(map.get(MAX_LENGTH)).append(" THEN 1 ELSE 0 END), COUNT(*) FROM ").append(table);
return builder.toString();
}
@Override
public String code() {
return "accuracy_key_length";
}
}

View File

@@ -0,0 +1,27 @@
package cn.datax.service.data.quality.schedule.rules;
import cn.datax.common.database.constants.DbType;
import java.util.Map;
/**
* 一致性核查
* 核查项:字典
* select sum(case when column not in ('0', '1') then 1 else 0 end), count(*) from table;
*/
public class ConsistentRule implements RuleItem {
private static String GB_ITEM = "gb_item";
@Override
public String parse(DbType dbType, String table, String column, Map<String, Object> map) {
final StringBuilder builder = new StringBuilder();
builder.append("SELECT SUM(CASE WHEN ").append(column).append(" NOT IN (").append(map.get(GB_ITEM)).append(") THEN 1 ELSE 0 END), COUNT(*) FROM ").append(table);
return builder.toString();
}
@Override
public String code() {
return "consistent_key";
}
}

View File

@@ -0,0 +1,25 @@
package cn.datax.service.data.quality.schedule.rules;
import cn.datax.common.database.constants.DbType;
import java.util.Map;
/**
* 完整性核查
* 核查项:非空
* select sum(case when column is not null and trim(column) != '' then 1 else 0 end), count(*) from table;
*/
public class IntegrityRule implements RuleItem {
@Override
public String parse(DbType dbType, String table, String column, Map<String, Object> map) {
final StringBuilder builder = new StringBuilder();
builder.append("SELECT SUM(CASE WHEN ").append(column).append(" IS NOT NULL AND TRIM(").append(column).append(") != '' THEN 0 ELSE 1 END), COUNT(*) FROM ").append(table);
return builder.toString();
}
@Override
public String code() {
return "integrity_key";
}
}

View File

@@ -0,0 +1,34 @@
package cn.datax.service.data.quality.schedule.rules;
import cn.datax.common.database.constants.DbType;
import java.util.Map;
/**
* 关联性核查
* select SUM(errorCount) errorCount, SUM(totalCount) totalCount
* FROM (
* select count(*) errorCount, 0 as totalCount from MAIN_TABLE a where not exists(select 1 from FOLLOW_TWO b where a.NAME = b.NAME)
* union select 0 as errorCount, count(*) totalCount from MAIN_TABLE
* ) temp;
*/
public class RelevanceRule implements RuleItem {
private static String RELATED_TABLE = "related_table";
private static String RELATED_COLUMN = "related_column";
@Override
public String parse(DbType dbType, String table, String column, Map<String, Object> map) {
final StringBuilder builder = new StringBuilder();
builder.append("SELECT SUM(errorCount) AS errorCount, SUM(totalCount) AS totalCount FROM (")
.append("SELECT COUNT(*) AS errorCount, 0 AS totalCount FROM ")
.append(table).append(" a WHERE NOT EXISTS (SELECT 1 FROM ").append(map.get(RELATED_TABLE)).append(" b WHERE a.").append(column).append(" = b.").append(map.get(RELATED_COLUMN)).append(")")
.append("UNION SELECT 0 AS errorCount, COUNT(*) AS totalCount FROM ").append(table).append(") TEMP");
return builder.toString();
}
@Override
public String code() {
return "relevance_key";
}
}

View File

@@ -0,0 +1,12 @@
package cn.datax.service.data.quality.schedule.rules;
import cn.datax.common.database.constants.DbType;
import java.util.Map;
public interface RuleItem {
String parse(DbType dbType, String table, String column, Map<String, Object> map);
String code();
}

View File

@@ -0,0 +1,22 @@
package cn.datax.service.data.quality.schedule.rules;
import java.util.HashMap;
import java.util.Map;
public class RuleItemRegistry {
private final Map<String, RuleItem> rule_item_map = new HashMap<>();
public RuleItemRegistry() {
this.rule_item_map.put("unique_key", new UniqueRule());
this.rule_item_map.put("consistent_key", new ConsistentRule());
this.rule_item_map.put("integrity_key", new IntegrityRule());
this.rule_item_map.put("relevance_key", new RelevanceRule());
this.rule_item_map.put("timeliness_key", new TimelinessRule());
this.rule_item_map.put("accuracy_key_length", new AccuracyLengthRule());
}
public RuleItem getRuleItem(String code) {
return this.rule_item_map.get(code);
}
}

View File

@@ -0,0 +1,42 @@
package cn.datax.service.data.quality.schedule.rules;
import cn.datax.common.database.constants.DbType;
import java.util.Map;
/**
* 及时性核查
*/
public class TimelinessRule implements RuleItem {
private static String THRESHOLD = "threshold";
@Override
public String parse(DbType dbType, String table, String column, Map<String, Object> map) {
final StringBuilder builder = new StringBuilder();
switch (dbType) {
case ORACLE:
case ORACLE_12C:
builder.append("SELECT SUM(CASE WHEN ROUND(TO_NUMBER(SYSDATE - ").append(column).append(")) >= ").append(map.get(THRESHOLD)).append(" THEN 1 ELSE 0 END), COUNT(*) FROM ").append(table);
break;
case MYSQL:
case MARIADB:
builder.append("SELECT SUM(CASE WHEN DATEDIFF(NOW(), ").append(column).append(") >= ").append(map.get(THRESHOLD)).append(" THEN 1 ELSE 0 END), COUNT(*) FROM ").append(table);
break;
case SQL_SERVER:
case SQL_SERVER2008:
builder.append("SELECT SUM(CASE WHEN DATEDIFF(DAY, ").append(column).append(", GETDATE()) >= ").append(map.get(THRESHOLD)).append(" THEN 1 ELSE 0 END), COUNT(*) FROM ").append(table);
break;
case POSTGRE_SQL:
case OTHER:
default:
break;
}
return builder.toString();
}
@Override
public String code() {
return "timeliness_key";
}
}

View File

@@ -0,0 +1,27 @@
package cn.datax.service.data.quality.schedule.rules;
import cn.datax.common.database.constants.DbType;
import java.util.Map;
/**
* 唯一性核查
* 核查项:主键
* select count(distinct id), count(*) from table;
*/
public class UniqueRule implements RuleItem {
@Override
public String parse(DbType dbType, String table, String column, Map<String, Object> map) {
final StringBuilder builder = new StringBuilder();
builder.append("SELECT totalCount - errorCount AS errorCount, totalCount FROM (");
builder.append("SELECT COUNT(DISTINCT ").append(column).append(") AS errorCount, COUNT(*) AS totalCount FROM ").append(table);
builder.append(") TEMP");
return builder.toString();
}
@Override
public String code() {
return "unique_key";
}
}

View File

@@ -0,0 +1,165 @@
package cn.datax.service.data.quality.schedule.task;
import cn.datax.common.core.DataConstant;
import cn.datax.common.database.DataSourceFactory;
import cn.datax.common.database.DbQuery;
import cn.datax.common.database.constants.DbQueryProperty;
import cn.datax.common.exception.DataException;
import cn.datax.common.utils.SpringContextHolder;
import cn.datax.service.data.metadata.api.dto.DbSchema;
import cn.datax.service.data.metadata.api.entity.MetadataSourceEntity;
import cn.datax.service.data.metadata.api.feign.MetadataSourceServiceFeign;
import cn.datax.service.data.quality.api.entity.CheckReportEntity;
import cn.datax.service.data.quality.api.entity.CheckRuleEntity;
import cn.datax.service.data.quality.api.entity.ScheduleLogEntity;
import cn.datax.service.data.quality.service.CheckReportService;
import cn.datax.service.data.quality.service.CheckRuleService;
import cn.datax.service.data.quality.service.ScheduleLogService;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.*;
@Slf4j
@Component("qualityTask")
public class QualityTask {
@Autowired
private CheckRuleService checkRuleService;
@Autowired
private CheckReportService checkReportService;
@Autowired
private ScheduleLogService scheduleLogService;
public void task(Map<String, Object> map) {
// 结果集
List<CheckReportEntity> result = new ArrayList<>();
// 获取可执行的核查规则
List<CheckRuleEntity> list = checkRuleService.list(Wrappers.<CheckRuleEntity>lambdaQuery().eq(CheckRuleEntity::getStatus, DataConstant.TrueOrFalse.TRUE.getKey()));
// 定义固定长度的线程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(50),
new BasicThreadFactory.Builder().namingPattern("executor-schedule-pool-%d").daemon(true).build());
// 定义计数器
final CountDownLatch latch = new CountDownLatch(list.size());
// Callable用于产生结果
List<TaskHander> tasks = new ArrayList<>();
list.forEach(rule -> {
TaskHander task = new TaskHander(latch, rule);
tasks.add(task);
});
List<Future<CheckReportEntity>> futures;
try {
futures = threadPoolExecutor.invokeAll(tasks);
// 处理线程返回结果
for (Future<CheckReportEntity> future : futures) {
result.add(future.get());
}
// 主线程阻塞,等待所有子线程执行完成
latch.await();
} catch (Exception e) {
e.printStackTrace();
}
// 关闭线程池
threadPoolExecutor.shutdown();
// 核查报告
result.forEach(s -> {
// 插入核查结果正常的数据
String status = StrUtil.isBlank(s.getCheckResult()) ? DataConstant.TrueOrFalse.TRUE.getKey() : DataConstant.TrueOrFalse.FALSE.getKey();
if (StrUtil.isBlank(s.getCheckResult())) {
s.setCheckBatch((String) map.get("batch"));
checkReportService.save(s);
// 更新最近核查批次号
LambdaUpdateWrapper<CheckRuleEntity> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.set(CheckRuleEntity::getLastCheckBatch, map.get("batch"));
updateWrapper.eq(CheckRuleEntity::getId, s.getCheckRuleId());
checkRuleService.update(updateWrapper);
}
// 定时任务日志
ScheduleLogEntity scheduleLogEntity = new ScheduleLogEntity();
scheduleLogEntity.setExecuteJobId((String) map.get("id"));
scheduleLogEntity.setExecuteBatch((String) map.get("batch"));
scheduleLogEntity.setExecuteDate(s.getCheckDate());
scheduleLogEntity.setExecuteRuleId(s.getCheckRuleId());
scheduleLogEntity.setExecuteResult(s.getCheckResult());
scheduleLogEntity.setStatus(status);
scheduleLogService.save(scheduleLogEntity);
});
}
static class TaskHander implements Callable<CheckReportEntity> {
private CountDownLatch latch;
private CheckRuleEntity checkRuleEntity;
public TaskHander(CountDownLatch latch, CheckRuleEntity checkRuleEntity) {
super();
this.latch = latch;
this.checkRuleEntity = checkRuleEntity;
}
@Override
public CheckReportEntity call() {
log.info("任务 - 规则id{},规则名称:{} 时间:{}", checkRuleEntity.getId(), checkRuleEntity.getRuleName(), System.currentTimeMillis());
CheckReportEntity checkReportEntity = new CheckReportEntity();
checkReportEntity.setCheckRuleId(checkRuleEntity.getId());
checkReportEntity.setCheckDate(LocalDateTime.now());
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
MetadataSourceServiceFeign metadataSourceServiceFeign = SpringContextHolder.getBean(MetadataSourceServiceFeign.class);
MetadataSourceEntity dataSource = Optional.ofNullable(metadataSourceServiceFeign.getMetadataSourceById(checkRuleEntity.getRuleSourceId())).orElseThrow(() -> new DataException("获取数据源接口出错"));
DbSchema dbSchema = dataSource.getDbSchema();
DbQueryProperty dbQueryProperty = new DbQueryProperty(dataSource.getDbType(), dbSchema.getHost(),
dbSchema.getUsername(), dbSchema.getPassword(), dbSchema.getPort(), dbSchema.getDbName(), dbSchema.getSid());
DataSourceFactory dataSourceFactory = SpringContextHolder.getBean(DataSourceFactory.class);
DbQuery dbQuery = Optional.ofNullable(dataSourceFactory.createDbQuery(dbQueryProperty)).orElseThrow(() -> new DataException("创建数据查询接口出错"));
conn = dbQuery.getConnection();
stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
rs = stmt.executeQuery(checkRuleEntity.getRuleSql());
while (rs.next()) {
Integer checkErrorCount = rs.getInt(1);
checkReportEntity.setCheckErrorCount(checkErrorCount);
Integer checkTotalCount = rs.getInt(2);
checkReportEntity.setCheckTotalCount(checkTotalCount);
}
} catch (Exception e) {
checkReportEntity.setCheckResult(e.getMessage());
} finally {
latch.countDown();
try {
if(rs != null){
rs.close();
}
if (stmt != null) {
stmt.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
checkReportEntity.setCheckResult("释放数据库连接出错");
}
return checkReportEntity;
}
}
}
}

View File

@@ -0,0 +1,36 @@
package cn.datax.service.data.quality.service;
import cn.datax.service.data.quality.api.entity.CheckReportEntity;
import cn.datax.common.base.BaseService;
import cn.datax.service.data.quality.api.entity.DataReportEntity;
import cn.datax.service.data.quality.api.query.CheckReportQuery;
import java.util.List;
import java.util.Map;
/**
* <p>
* 核查报告信息表 服务类
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
public interface CheckReportService extends BaseService<CheckReportEntity> {
CheckReportEntity getCheckReportById(String id);
/**
* 按数据源统计
* @return
*/
List<DataReportEntity> getReportBySource(String checkDate);
/**
* 按规则类型统计
* @return
*/
List<DataReportEntity> getReportByType(String checkDate);
Map<String, Object> getReportDetail(String checkDate);
}

View File

@@ -0,0 +1,30 @@
package cn.datax.service.data.quality.service;
import cn.datax.service.data.quality.api.entity.CheckRuleEntity;
import cn.datax.service.data.quality.api.dto.CheckRuleDto;
import cn.datax.common.base.BaseService;
import java.util.List;
/**
* <p>
* 核查规则信息表 服务类
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
public interface CheckRuleService extends BaseService<CheckRuleEntity> {
CheckRuleEntity saveCheckRule(CheckRuleDto checkRule);
CheckRuleEntity updateCheckRule(CheckRuleDto checkRule);
CheckRuleEntity getCheckRuleById(String id);
void deleteCheckRuleById(String id);
void deleteCheckRuleBatch(List<String> ids);
CheckRuleEntity getBySourceId(String sourceId);
}

View File

@@ -0,0 +1,17 @@
package cn.datax.service.data.quality.service;
import cn.datax.service.data.quality.api.entity.RuleItemEntity;
import cn.datax.common.base.BaseService;
/**
* <p>
* 规则核查项信息表 服务类
* </p>
*
* @author AllDataDC
* @date 2022-11-15
*/
public interface RuleItemService extends BaseService<RuleItemEntity> {
RuleItemEntity getRuleItemById(String id);
}

View File

@@ -0,0 +1,17 @@
package cn.datax.service.data.quality.service;
import cn.datax.service.data.quality.api.entity.RuleLevelEntity;
import cn.datax.common.base.BaseService;
/**
* <p>
* 规则级别信息表 服务类
* </p>
*
* @author AllDataDC
* @date 2022-11-14
*/
public interface RuleLevelService extends BaseService<RuleLevelEntity> {
RuleLevelEntity getRuleLevelById(String id);
}

View File

@@ -0,0 +1,22 @@
package cn.datax.service.data.quality.service;
import cn.datax.service.data.quality.api.entity.RuleTypeEntity;
import cn.datax.common.base.BaseService;
import cn.datax.service.data.quality.api.entity.RuleTypeReportEntity;
import java.util.List;
/**
* <p>
* 规则类型信息表 服务类
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
public interface RuleTypeService extends BaseService<RuleTypeEntity> {
RuleTypeEntity getRuleTypeById(String id);
List<RuleTypeReportEntity> getRuleTypeListForReport();
}

View File

@@ -0,0 +1,23 @@
package cn.datax.service.data.quality.service;
import cn.datax.service.data.quality.api.entity.ScheduleJobEntity;
import cn.datax.common.base.BaseService;
/**
* <p>
* 数据质量监控任务信息表 服务类
* </p>
*
* @author AllDataDC
* @date 2022-11-29
*/
public interface ScheduleJobService extends BaseService<ScheduleJobEntity> {
ScheduleJobEntity getScheduleJobById(String id);
void pauseScheduleJobById(String id);
void resumeScheduleJobById(String id);
void runScheduleJobById(String id);
}

View File

@@ -0,0 +1,23 @@
package cn.datax.service.data.quality.service;
import cn.datax.service.data.quality.api.entity.ScheduleLogEntity;
import cn.datax.common.base.BaseService;
import java.util.List;
/**
* <p>
* 数据质量监控任务日志信息表 服务类
* </p>
*
* @author AllDataDC
* @date 2022-11-13
*/
public interface ScheduleLogService extends BaseService<ScheduleLogEntity> {
ScheduleLogEntity getScheduleLogById(String id);
void deleteScheduleLogById(String id);
void deleteScheduleLogBatch(List<String> ids);
}

View File

@@ -0,0 +1,103 @@
package cn.datax.service.data.quality.service.impl;
import cn.datax.service.data.quality.api.entity.CheckReportEntity;
import cn.datax.service.data.quality.api.entity.DataReportEntity;
import cn.datax.service.data.quality.api.entity.RuleLevelEntity;
import cn.datax.service.data.quality.api.entity.RuleTypeEntity;
import cn.datax.service.data.quality.api.query.CheckReportQuery;
import cn.datax.service.data.quality.dao.RuleLevelDao;
import cn.datax.service.data.quality.dao.RuleTypeDao;
import cn.datax.service.data.quality.service.CheckReportService;
import cn.datax.service.data.quality.mapstruct.CheckReportMapper;
import cn.datax.service.data.quality.dao.CheckReportDao;
import cn.datax.common.base.BaseServiceImpl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
/**
* <p>
* 核查报告信息表 服务实现类
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class CheckReportServiceImpl extends BaseServiceImpl<CheckReportDao, CheckReportEntity> implements CheckReportService {
@Autowired
private CheckReportDao checkReportDao;
@Autowired
private CheckReportMapper checkReportMapper;
@Autowired
private RuleLevelDao ruleLevelDao;
@Autowired
private RuleTypeDao ruleTypeDao;
@Override
public CheckReportEntity getCheckReportById(String id) {
CheckReportEntity checkReportEntity = super.getById(id);
return checkReportEntity;
}
@Override
public List<DataReportEntity> getReportBySource(String checkDate) {
List<RuleLevelEntity> ruleLevelList = ruleLevelDao.selectList(Wrappers.emptyWrapper());
List<DataReportEntity> list = checkReportDao.getReportBySource(checkDate);
// 补全数据
List<DataReportEntity> differenceReportList = new ArrayList<>();
// 补全数据源分组缺失的规则级别数据
Map<String, List<DataReportEntity>> sourceMap = list.stream().collect(Collectors.groupingBy(DataReportEntity::getRuleSourceId));
Iterator<Map.Entry<String, List<DataReportEntity>>> sourceIterator = sourceMap.entrySet().iterator();
while (sourceIterator.hasNext()) {
Map.Entry<String, List<DataReportEntity>> sourceEntry = sourceIterator.next();
List<DataReportEntity> entryValue = sourceEntry.getValue();
DataReportEntity dataReportEntity = entryValue.get(0);
// 差集 (ruleLevelList - entryValue)
ruleLevelList.stream().filter(item -> entryValue.stream().map(DataReportEntity::getRuleLevelId).noneMatch(id -> Objects.equals(item.getId(), id)))
.forEach(s -> {
DataReportEntity report = new DataReportEntity();
report.setRuleSourceId(dataReportEntity.getRuleSourceId());
report.setRuleSourceName(dataReportEntity.getRuleSourceName());
report.setRuleLevelId(s.getId());
report.setRuleLevelName(s.getName());
report.setCheckErrorCount(0);
differenceReportList.add(report);
});
}
list.addAll(differenceReportList);
// 排序
list = list.stream().sorted(Comparator.comparing(DataReportEntity::getRuleSourceId).thenComparing(DataReportEntity::getRuleLevelId)).collect(Collectors.toList());
return list;
}
@Override
public List<DataReportEntity> getReportByType(String checkDate) {
List<DataReportEntity> list = checkReportDao.getReportByType(checkDate);
// 排序
list = list.stream().sorted(Comparator.comparing(DataReportEntity::getRuleTypeId)).collect(Collectors.toList());
return list;
}
@Override
public Map<String, Object> getReportDetail(String checkDate) {
Map<String, Object> map = new HashMap<>();
List<RuleTypeEntity> ruleTypeList = ruleTypeDao.selectList(Wrappers.emptyWrapper());
List<DataReportEntity> dataReportList = checkReportDao.getReportDetail(checkDate);
Map<String, List<DataReportEntity>> listMap = dataReportList.stream().collect(Collectors.groupingBy(DataReportEntity::getRuleTypeCode));
ruleTypeList.forEach(s -> {
map.put(s.getCode(), listMap.get(s.getCode()));
});
return map;
}
}

View File

@@ -0,0 +1,142 @@
package cn.datax.service.data.quality.service.impl;
import cn.datax.common.base.BaseServiceImpl;
import cn.datax.common.core.RedisConstant;
import cn.datax.common.database.constants.DbType;
import cn.datax.common.redis.service.RedisService;
import cn.datax.service.data.quality.api.dto.Accuracy;
import cn.datax.service.data.quality.api.dto.CheckRuleDto;
import cn.datax.service.data.quality.api.dto.Consistent;
import cn.datax.service.data.quality.api.dto.Relevance;
import cn.datax.service.data.quality.api.dto.RuleConfig;
import cn.datax.service.data.quality.api.dto.Timeliness;
import cn.datax.service.data.quality.api.entity.CheckRuleEntity;
import cn.datax.service.data.quality.api.enums.RuleItem;
import cn.datax.service.data.quality.dao.CheckRuleDao;
import cn.datax.service.data.quality.mapstruct.CheckRuleMapper;
import cn.datax.service.data.quality.schedule.CheckRuleFactory;
import cn.datax.service.data.quality.service.CheckRuleService;
import cn.datax.service.data.standard.api.entity.DictEntity;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* <p>
* 核查规则信息表 服务实现类
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class CheckRuleServiceImpl extends BaseServiceImpl<CheckRuleDao, CheckRuleEntity> implements CheckRuleService {
@Autowired
private CheckRuleDao checkRuleDao;
@Autowired
private CheckRuleMapper checkRuleMapper;
@Autowired
private RedisService redisService;
private static String BIND_GB_CODE = "gb_code";
private static String BIND_GB_NAME = "gb_name";
@Override
@Transactional(rollbackFor = Exception.class)
public CheckRuleEntity saveCheckRule(CheckRuleDto checkRuleDto) {
CheckRuleEntity checkRule = checkRuleMapper.toEntity(checkRuleDto);
String sql = parseSql(checkRule);
checkRule.setRuleSql(sql);
checkRuleDao.insert(checkRule);
return checkRule;
}
@Override
@Transactional(rollbackFor = Exception.class)
public CheckRuleEntity updateCheckRule(CheckRuleDto checkRuleDto) {
CheckRuleEntity checkRule = checkRuleMapper.toEntity(checkRuleDto);
String sql = parseSql(checkRule);
checkRule.setRuleSql(sql);
checkRuleDao.updateById(checkRule);
return checkRule;
}
@Override
public CheckRuleEntity getCheckRuleById(String id) {
CheckRuleEntity checkRuleEntity = super.getById(id);
return checkRuleEntity;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteCheckRuleById(String id) {
checkRuleDao.deleteById(id);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteCheckRuleBatch(List<String> ids) {
checkRuleDao.deleteBatchIds(ids);
}
@Override
public CheckRuleEntity getBySourceId(String sourceId) {
return checkRuleDao.selectOne(new QueryWrapper<CheckRuleEntity>().eq("rule_source_id", sourceId).last("limit 1"));
}
private String parseSql(CheckRuleEntity checkRule) {
RuleConfig ruleConfig = checkRule.getRuleConfig();
Map<String, Object> map = new HashMap<>();
RuleItem ruleItem = RuleItem.getRuleItem(ruleConfig.getRuleItemCode());
switch (ruleItem) {
case Unique:
case Integrity:
break;
// 一致性参数处理
case Consistent:
Consistent consistent = ruleConfig.getConsistent();
List<DictEntity> dictEntityList = (List<DictEntity>) redisService.hget(RedisConstant.STANDARD_DICT_KEY, consistent.getGbTypeId());
String collect = dictEntityList.stream().map(s -> {
if (BIND_GB_CODE.equals(consistent.getBindGbColumn())) {
return "\'" + s.getGbCode() + "\'";
} else {
return "\'" + s.getGbName() + "\'";
}
}).collect(Collectors.joining(","));
map.put("gb_item", collect);
break;
// 关联性参数处理
case Relevance:
Relevance relevance = ruleConfig.getRelevance();
map.put("related_table", relevance.getRelatedTable());
map.put("related_column", relevance.getRelatedColumn());
break;
// 及时性参数处理
case Timeliness:
Timeliness timeliness = ruleConfig.getTimeliness();
map.put("threshold", timeliness.getThreshold());
break;
// 准确性参数处理
case AccuracyLength:
Accuracy accuracy = ruleConfig.getAccuracy();
map.put("max_length", accuracy.getMaxLength());
break;
default:
return null;
}
DbType dbType = DbType.getDbType(checkRule.getRuleDbType());
String sql = CheckRuleFactory.getRuleItem(ruleConfig.getRuleItemCode()).parse(dbType, checkRule.getRuleTable(), checkRule.getRuleColumn(), map);
return sql;
}
}

View File

@@ -0,0 +1,36 @@
package cn.datax.service.data.quality.service.impl;
import cn.datax.service.data.quality.api.entity.RuleItemEntity;
import cn.datax.service.data.quality.service.RuleItemService;
import cn.datax.service.data.quality.mapstruct.RuleItemMapper;
import cn.datax.service.data.quality.dao.RuleItemDao;
import cn.datax.common.base.BaseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
/**
* <p>
* 规则核查项信息表 服务实现类
* </p>
*
* @author AllDataDC
* @date 2022-11-15
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class RuleItemServiceImpl extends BaseServiceImpl<RuleItemDao, RuleItemEntity> implements RuleItemService {
@Autowired
private RuleItemDao ruleItemDao;
@Autowired
private RuleItemMapper ruleItemMapper;
@Override
public RuleItemEntity getRuleItemById(String id) {
RuleItemEntity ruleItemEntity = super.getById(id);
return ruleItemEntity;
}
}

View File

@@ -0,0 +1,36 @@
package cn.datax.service.data.quality.service.impl;
import cn.datax.service.data.quality.api.entity.RuleLevelEntity;
import cn.datax.service.data.quality.service.RuleLevelService;
import cn.datax.service.data.quality.mapstruct.RuleLevelMapper;
import cn.datax.service.data.quality.dao.RuleLevelDao;
import cn.datax.common.base.BaseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
/**
* <p>
* 规则级别信息表 服务实现类
* </p>
*
* @author AllDataDC
* @date 2022-11-14
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class RuleLevelServiceImpl extends BaseServiceImpl<RuleLevelDao, RuleLevelEntity> implements RuleLevelService {
@Autowired
private RuleLevelDao ruleLevelDao;
@Autowired
private RuleLevelMapper ruleLevelMapper;
@Override
public RuleLevelEntity getRuleLevelById(String id) {
RuleLevelEntity ruleLevelEntity = super.getById(id);
return ruleLevelEntity;
}
}

View File

@@ -0,0 +1,45 @@
package cn.datax.service.data.quality.service.impl;
import cn.datax.service.data.quality.api.entity.RuleTypeEntity;
import cn.datax.service.data.quality.api.entity.RuleTypeReportEntity;
import cn.datax.service.data.quality.service.RuleTypeService;
import cn.datax.service.data.quality.mapstruct.RuleTypeMapper;
import cn.datax.service.data.quality.dao.RuleTypeDao;
import cn.datax.common.base.BaseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* <p>
* 规则类型信息表 服务实现类
* </p>
*
* @author AllDataDC
* @date 2022-11-27
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class RuleTypeServiceImpl extends BaseServiceImpl<RuleTypeDao, RuleTypeEntity> implements RuleTypeService {
@Autowired
private RuleTypeDao ruleTypeDao;
@Autowired
private RuleTypeMapper ruleTypeMapper;
@Override
public RuleTypeEntity getRuleTypeById(String id) {
RuleTypeEntity ruleTypeEntity = super.getById(id);
return ruleTypeEntity;
}
@Override
public List<RuleTypeReportEntity> getRuleTypeListForReport() {
List<RuleTypeReportEntity> list = ruleTypeDao.selectListForReport();
return list;
}
}

View File

@@ -0,0 +1,66 @@
package cn.datax.service.data.quality.service.impl;
import cn.datax.common.core.DataConstant;
import cn.datax.service.data.quality.api.entity.ScheduleJobEntity;
import cn.datax.service.data.quality.schedule.CronTaskRegistrar;
import cn.datax.service.data.quality.schedule.SchedulingRunnable;
import cn.datax.service.data.quality.service.ScheduleJobService;
import cn.datax.service.data.quality.mapstruct.ScheduleJobMapper;
import cn.datax.service.data.quality.dao.ScheduleJobDao;
import cn.datax.common.base.BaseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
/**
* <p>
* 数据质量监控任务信息表 服务实现类
* </p>
*
* @author AllDataDC
* @date 2022-11-29
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class ScheduleJobServiceImpl extends BaseServiceImpl<ScheduleJobDao, ScheduleJobEntity> implements ScheduleJobService {
@Autowired
private ScheduleJobDao scheduleJobDao;
@Autowired
private CronTaskRegistrar cronTaskRegistrar;
@Override
public ScheduleJobEntity getScheduleJobById(String id) {
ScheduleJobEntity scheduleJobEntity = super.getById(id);
return scheduleJobEntity;
}
@Override
public void pauseScheduleJobById(String id) {
ScheduleJobEntity scheduleJobEntity = super.getById(id);
SchedulingRunnable task = new SchedulingRunnable(id, scheduleJobEntity.getBeanName(), scheduleJobEntity.getMethodName(), scheduleJobEntity.getMethodParams());
cronTaskRegistrar.removeCronTask(task);
scheduleJobEntity.setStatus(DataConstant.TrueOrFalse.FALSE.getKey());
scheduleJobDao.updateById(scheduleJobEntity);
}
@Override
public void resumeScheduleJobById(String id) {
ScheduleJobEntity scheduleJobEntity = super.getById(id);
SchedulingRunnable task = new SchedulingRunnable(id, scheduleJobEntity.getBeanName(), scheduleJobEntity.getMethodName(), scheduleJobEntity.getMethodParams());
cronTaskRegistrar.addCronTask(task, scheduleJobEntity.getCronExpression());
scheduleJobEntity.setStatus(DataConstant.TrueOrFalse.TRUE.getKey());
scheduleJobDao.updateById(scheduleJobEntity);
}
@Override
@Async("taskExecutor")
public void runScheduleJobById(String id) {
ScheduleJobEntity scheduleJobEntity = super.getById(id);
SchedulingRunnable task = new SchedulingRunnable(id, scheduleJobEntity.getBeanName(), scheduleJobEntity.getMethodName(), scheduleJobEntity.getMethodParams());
task.run();
}
}

View File

@@ -0,0 +1,50 @@
package cn.datax.service.data.quality.service.impl;
import cn.datax.service.data.quality.api.entity.ScheduleLogEntity;
import cn.datax.service.data.quality.mapstruct.ScheduleLogMapper;
import cn.datax.service.data.quality.service.ScheduleLogService;
import cn.datax.service.data.quality.dao.ScheduleLogDao;
import cn.datax.common.base.BaseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* <p>
* 数据质量监控任务日志信息表 服务实现类
* </p>
*
* @author AllDataDC
* @date 2022-11-13
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class ScheduleLogServiceImpl extends BaseServiceImpl<ScheduleLogDao, ScheduleLogEntity> implements ScheduleLogService {
@Autowired
private ScheduleLogDao scheduleLogDao;
@Autowired
private ScheduleLogMapper scheduleLogMapper;
@Override
public ScheduleLogEntity getScheduleLogById(String id) {
ScheduleLogEntity scheduleLogEntity = super.getById(id);
return scheduleLogEntity;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteScheduleLogById(String id) {
scheduleLogDao.deleteById(id);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteScheduleLogBatch(List<String> ids) {
scheduleLogDao.deleteBatchIds(ids);
}
}

View File

@@ -0,0 +1,30 @@
server:
port: 8826
spring:
application:
name: service-data-quality
profiles:
active: dev
cloud:
config:
label: master
name: ${spring.application.name}
profile: ${spring.profiles.active}
discovery:
enabled: true
service-id: config
# 注册中心配置
eureka:
instance:
lease-renewal-interval-in-seconds: 20
prefer-ip-address: true
ip-address: 192.168.1.169
client:
register-with-eureka: true
fetch-registry: true
instance-info-replication-interval-seconds: 30
registry-fetch-interval-seconds: 3
service-url:
defaultZone: http://192.168.1.169:8610/eureka

View File

@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<springProperty scope="context" name="springAppName" source="spring.application.name"/>
<property name="log.path" value="logs/service-data-quality"/>
<property name="log.maxHistory" value="15"/>
<property name="log.totalSizeCap" value="500MB"/>
<property name="log.maxFileSize" value="10MB"/>
<property name="log.colorPattern"
value="%magenta(%d{yyyy-MM-dd HH:mm:ss}) %highlight(%-5level) %boldCyan(${springAppName:-}) %yellow(%thread) %green(%logger) %msg%n"/>
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5level ${springAppName:-} %thread %logger %msg%n"/>
<!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.colorPattern}</pattern>
</encoder>
</appender>
<!--输出到文件-->
<!-- RollingFileAppender滚动记录文件先将日志记录到指定文件当符合某个条件时将日志记录到其他文件 -->
<!-- 以下的大概意思是1.先按日期存日志日期变了将前一天的日志文件名重命名为XXX%日期%索引新的日志仍然是project_info.log -->
<!-- 2.如果日期没有发生变化但是当前日志的文件大小超过10MB时对当前日志进行分割 重命名-->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日志文件路径和名称-->
<File>${log.path}/info/info.log</File>
<!--是否追加到文件末尾,默认为true-->
<append>true</append>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 日志文件的名字会根据fileNamePattern的值每隔一段时间改变一次 -->
<!-- 文件名logs/project_info.2017-12-05.0.log -->
<!-- 注意SizeAndTimeBasedRollingPolicy中 i和d令牌都是强制性的必须存在要不会报错 -->
<fileNamePattern>${log.path}/info/info.%d.%i.log</fileNamePattern>
<!-- 每产生一个日志文件该日志文件的保存期限为30天, ps:maxHistory的单位是根据fileNamePattern中的翻转策略自动推算出来的,例如上面选用了yyyy-MM-dd,则单位为天
如果上面选用了yyyy-MM,则单位为月,另外上面的单位默认为yyyy-MM-dd-->
<MaxHistory>${log.maxHistory}</MaxHistory>
<!-- 每个日志文件到2mb的时候开始切分最多保留30天但最大到500MB哪怕没到30天也要删除多余的日志 -->
<totalSizeCap>${log.totalSizeCap}</totalSizeCap>
<!-- maxFileSize:这是活动文件的大小默认值是10MB测试时可改成5KB看效果 -->
<maxFileSize>${log.maxFileSize}</maxFileSize>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${log.path}/error/error.log</File>
<append>true</append>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/error/error.%d.%i.log</fileNamePattern>
<MaxHistory>${log.maxHistory}</MaxHistory>
<totalSizeCap>${log.totalSizeCap}</totalSizeCap>
<maxFileSize>${log.maxFileSize}</maxFileSize>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<root level="debug">
<appender-ref ref="console"/>
</root>
<root level="info">
<appender-ref ref="file_info"/>
<appender-ref ref="file_error"/>
</root>
</configuration>

View File

@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.datax.service.data.quality.dao.CheckReportDao">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="cn.datax.service.data.quality.api.entity.CheckReportEntity">
<result column="id" property="id" />
<result column="check_rule_id" property="checkRuleId" />
<result column="check_date" property="checkDate" />
<result column="check_result" property="checkResult" />
<result column="check_total_count" property="checkTotalCount" />
<result column="check_error_count" property="checkErrorCount" />
<result column="check_batch" property="checkBatch" />
</resultMap>
<resultMap id="ExtendResultMap" type="cn.datax.service.data.quality.api.entity.CheckReportEntity" extends="BaseResultMap">
<result column="rule_name" property="ruleName" />
<result column="rule_type" property="ruleType" />
<result column="rule_source" property="ruleSource" />
<result column="rule_table" property="ruleTable" />
<result column="rule_column" property="ruleColumn" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id,
check_rule_id, check_date, check_result, check_total_count, check_error_count, check_batch
</sql>
<sql id="Report_Column_List">
${alias}.id,
${alias}.check_rule_id, ${alias}.check_date, ${alias}.check_result, ${alias}.check_total_count, ${alias}.check_error_count, ${alias}.check_batch
</sql>
<select id="selectPage" resultMap="ExtendResultMap">
SELECT r.rule_name, t.name as rule_type, r.rule_source, r.rule_table, r.rule_column,
<include refid="Report_Column_List"><property name="alias" value="c"/></include>
FROM quality_check_report c
LEFT JOIN quality_check_rule r ON r.id = c.check_rule_id
LEFT JOIN quality_rule_type t ON t.id = r.rule_type_id
${ew.customSqlSegment}
</select>
<resultMap id="ReportResultMap" type="cn.datax.service.data.quality.api.entity.DataReportEntity">
<result column="rule_type_id" property="ruleTypeId" />
<result column="rule_type_name" property="ruleTypeName" />
<result column="rule_id" property="ruleId" />
<result column="rule_name" property="ruleName" />
<result column="rule_source_id" property="ruleSourceId" />
<result column="rule_source_name" property="ruleSourceName" />
<result column="rule_level_id" property="ruleLevelId" />
<result column="rule_level_name" property="ruleLevelName" />
<result column="check_error_count" property="checkErrorCount" />
</resultMap>
<resultMap id="ExtendReportResultMap" type="cn.datax.service.data.quality.api.entity.DataReportEntity" extends="ReportResultMap">
<result column="rule_type_code" property="ruleTypeCode" />
<result column="rule_table_name" property="ruleTableName" />
<result column="rule_table_comment" property="ruleTableComment" />
<result column="rule_column_name" property="ruleColumnName" />
<result column="rule_column_comment" property="ruleColumnComment" />
<result column="check_total_count" property="checkTotalCount" />
</resultMap>
<select id="getReportBySource" resultMap="ReportResultMap">
SELECT temp.*, l.name AS rule_level_name from (
SELECT r.rule_source_id, r.rule_source AS rule_source_name, r.rule_level_id,
COALESCE(SUM(t.check_error_count), 0) AS check_error_count
FROM quality_check_rule r
LEFT JOIN quality_check_report t ON t.check_rule_id = r.id and
t.check_date = (select max(check_date) from quality_check_report where check_rule_id = r.id and date(check_date) = #{checkDate})
GROUP BY r.rule_source_id, r.rule_source, r.rule_level_id
) temp LEFT JOIN quality_rule_level l ON l.id = temp.rule_level_id
</select>
<select id="getReportByType" resultMap="ReportResultMap">
SELECT type.id AS rule_type_id, type.name AS rule_type_name, rule.id AS rule_id, rule.rule_name,
level.id AS rule_level_id, level.name AS rule_level_name, COALESCE(report.check_error_count, 0) AS check_error_count
FROM quality_check_rule rule
LEFT JOIN quality_rule_type type ON type.id = rule.rule_type_id
LEFT JOIN quality_rule_level level ON level.id = rule.rule_level_id
LEFT JOIN quality_check_report report ON report.check_rule_id = rule.id AND
report.check_date = (select max(check_date) from quality_check_report where check_rule_id = rule.id and date(check_date) = #{checkDate})
</select>
<select id="getReportDetail" resultMap="ExtendReportResultMap">
SELECT type.id AS rule_type_id, type.code AS rule_type_code,
level.id AS rule_level_id, level.name AS rule_level_name,
rule.id AS rule_id, rule.rule_name, rule.rule_source AS rule_source_name, rule.rule_table AS rule_table_name, rule.rule_table_comment, rule.rule_column AS rule_column_name, rule.rule_column_comment,
COALESCE(report.check_total_count, 0) AS check_total_count, COALESCE(report.check_error_count, 0) AS check_error_count
FROM quality_check_rule rule
LEFT JOIN quality_rule_type type ON type.id = rule.rule_type_id
LEFT JOIN quality_rule_level level ON level.id = rule.rule_level_id
LEFT JOIN quality_check_report report ON report.check_rule_id = rule.id where
report.check_date = (select max(check_date) from quality_check_report where check_rule_id = rule.id and date(check_date) = #{checkDate})
</select>
</mapper>

View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.datax.service.data.quality.dao.CheckRuleDao">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="cn.datax.service.data.quality.api.entity.CheckRuleEntity">
<result column="id" property="id" />
<result column="status" property="status" />
<result column="create_by" property="createBy" />
<result column="create_time" property="createTime" />
<result column="create_dept" property="createDept" />
<result column="update_by" property="updateBy" />
<result column="update_time" property="updateTime" />
<result column="remark" property="remark" />
<result column="rule_name" property="ruleName" />
<result column="rule_type_id" property="ruleTypeId" />
<result column="rule_item_id" property="ruleItemId" />
<result column="rule_level_id" property="ruleLevelId" />
<result column="rule_db_type" property="ruleDbType" />
<result column="rule_source_id" property="ruleSourceId" />
<result column="rule_source" property="ruleSource" />
<result column="rule_table_id" property="ruleTableId" />
<result column="rule_table" property="ruleTable" />
<result column="rule_table_comment" property="ruleTableComment" />
<result column="rule_column_id" property="ruleColumnId" />
<result column="rule_column" property="ruleColumn" />
<result column="rule_column_comment" property="ruleColumnComment" />
<result column="last_check_batch" property="lastCheckBatch" />
</resultMap>
<resultMap id="ExtendResultMap" type="cn.datax.service.data.quality.api.entity.CheckRuleEntity" extends="BaseResultMap">
<result column="rule_type" property="ruleType" />
<result column="rule_level" property="ruleLevel" />
<result column="config_json" property="ruleConfig" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
<result column="rule_sql" property="ruleSql" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id,
status,
create_by,
create_time,
create_dept,
update_by,
update_time,
remark,
rule_name, rule_type_id, rule_item_id, rule_level_id, rule_db_type, rule_source_id, rule_source, rule_table_id, rule_table, rule_table_comment,
rule_column_id, rule_column, rule_column_comment, last_check_batch
</sql>
<sql id="Rule_Column_List">
${alias}.id,
${alias}.status,
${alias}.create_by,
${alias}.create_time,
${alias}.create_dept,
${alias}.update_by,
${alias}.update_time,
${alias}.remark,
${alias}.rule_name, ${alias}.rule_type_id, ${alias}.rule_item_id, ${alias}.rule_level_id, ${alias}.rule_db_type, ${alias}.rule_source_id, ${alias}.rule_source,
${alias}.rule_table_id, ${alias}.rule_table, ${alias}.rule_table_comment, ${alias}.rule_column_id, ${alias}.rule_column, ${alias}.rule_column_comment, ${alias}.last_check_batch
</sql>
<select id="selectPage" resultMap="ExtendResultMap">
SELECT t.name as rule_type, l.name as rule_level,
<include refid="Rule_Column_List"><property name="alias" value="r"/></include>
FROM quality_check_rule r
LEFT JOIN quality_rule_type t ON t.id = r.rule_type_id
LEFT JOIN quality_rule_level l ON l.id = r.rule_level_id
${ew.customSqlSegment}
</select>
<select id="selectById" resultMap="ExtendResultMap">
SELECT config_json,
<include refid="Base_Column_List"></include>
FROM quality_check_rule
WHERE 1=1 AND id = #{id}
</select>
<select id="selectList" resultMap="ExtendResultMap">
SELECT rule_sql,
<include refid="Base_Column_List"></include>
FROM quality_check_rule
${ew.customSqlSegment}
</select>
</mapper>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.datax.service.data.quality.dao.RuleItemDao">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="cn.datax.service.data.quality.api.entity.RuleItemEntity">
<result column="id" property="id" />
<result column="rule_type_id" property="ruleTypeId" />
<result column="item_code" property="itemCode" />
<result column="item_explain" property="itemExplain" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id,
rule_type_id, item_code, item_explain
</sql>
</mapper>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.datax.service.data.quality.dao.RuleLevelDao">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="cn.datax.service.data.quality.api.entity.RuleLevelEntity">
<result column="id" property="id" />
<result column="code" property="code" />
<result column="name" property="name" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id,
code, name
</sql>
</mapper>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.datax.service.data.quality.dao.RuleTypeDao">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="cn.datax.service.data.quality.api.entity.RuleTypeEntity">
<result column="id" property="id" />
<result column="name" property="name" />
<result column="code" property="code" />
</resultMap>
<resultMap id="ExtendResultMap" type="cn.datax.service.data.quality.api.entity.RuleTypeReportEntity" extends="BaseResultMap">
<result column="check_error_count" property="checkErrorCount" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id,
name, code
</sql>
<select id="selectListForReport" resultMap="ExtendResultMap">
SELECT t.id, t.name,
(SELECT COALESCE(SUM(c.check_error_count), 0) FROM quality_check_rule r
LEFT JOIN quality_check_report c ON c.check_rule_id = r.id AND c.check_batch = r.last_check_batch
WHERE r.rule_type_id = t.id) AS check_error_count
FROM quality_rule_type t
</select>
</mapper>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.datax.service.data.quality.dao.ScheduleJobDao">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="cn.datax.service.data.quality.api.entity.ScheduleJobEntity">
<result column="id" property="id" />
<result column="status" property="status" />
<result column="job_name" property="jobName" />
<result column="bean_name" property="beanName" />
<result column="method_name" property="methodName" />
<result column="method_params" property="methodParams" />
<result column="cron_expression" property="cronExpression" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id,
status,
job_name, bean_name, method_name, method_params, cron_expression
</sql>
</mapper>

Some files were not shown because too many files have changed in this diff Show More