检查实体类是否少字段
This commit is contained in:
parent
dedfc336cb
commit
a7c3b61680
@ -0,0 +1,500 @@
|
||||
package com.zhgd.xmgl.modules.validator;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.sql.DataSource;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class BulkEntityValidator {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("db1DataSource")
|
||||
private DataSource dataSource;
|
||||
|
||||
private final Map<String, List<String>> tableColumnsCache = new ConcurrentHashMap<>();
|
||||
private final ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
|
||||
private final MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
|
||||
|
||||
/**
|
||||
* 应用启动时自动验证所有实体类
|
||||
*/
|
||||
@PostConstruct
|
||||
public void autoValidateOnStartup() {
|
||||
log.info("开始自动验证实体类与数据库表映射...");
|
||||
try {
|
||||
Map<String, ValidationResult> results = validateAllEntitiesInProject();
|
||||
printValidationSummary(results);
|
||||
} catch (Exception e) {
|
||||
log.error("实体类映射验证失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证项目中所有实体类 - 返回验证结果
|
||||
*/
|
||||
public Map<String, ValidationResult> validateAllEntitiesInProject() {
|
||||
// 常见的实体类包路径,可以根据实际情况调整
|
||||
String[] commonEntityPackages = {
|
||||
"com.zhgd.xmgl.modules.**.entity"
|
||||
};
|
||||
|
||||
Map<String, ValidationResult> allResults = new LinkedHashMap<>();
|
||||
|
||||
for (String basePackage : commonEntityPackages) {
|
||||
try {
|
||||
Map<String, ValidationResult> packageResults = validatePackageEntities(basePackage);
|
||||
allResults.putAll(packageResults);
|
||||
} catch (Exception e) {
|
||||
log.warn("扫描包 {} 失败: {}", basePackage, e.getMessage());
|
||||
allResults.put(basePackage, ValidationResult.error(basePackage, "扫描包失败: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
return allResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证指定包下的所有实体类
|
||||
*/
|
||||
public Map<String, ValidationResult> validatePackageEntities(String basePackage) {
|
||||
log.info("开始扫描包: {}", basePackage);
|
||||
Map<String, ValidationResult> results = new LinkedHashMap<>();
|
||||
|
||||
Set<Class<?>> entityClasses = findEntitiesInPackage(basePackage);
|
||||
log.info("在包 {} 中找到 {} 个实体类", basePackage, entityClasses.size());
|
||||
|
||||
for (Class<?> entityClass : entityClasses) {
|
||||
try {
|
||||
ValidationResult result = validateSingleEntity(entityClass);
|
||||
results.put(entityClass.getSimpleName(), result);
|
||||
} catch (Exception e) {
|
||||
log.error("验证实体类 {} 失败: {}", entityClass.getSimpleName(), e.getMessage());
|
||||
results.put(entityClass.getSimpleName(),
|
||||
ValidationResult.error(entityClass.getSimpleName(), e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证单个实体类
|
||||
*/
|
||||
public ValidationResult validateSingleEntity(Class<?> entityClass) {
|
||||
TableName tableAnnotation = entityClass.getAnnotation(TableName.class);
|
||||
if (tableAnnotation == null) {
|
||||
return ValidationResult.error(entityClass.getSimpleName(), "缺少 @TableName 注解");
|
||||
}
|
||||
|
||||
String tableName = tableAnnotation.value();
|
||||
if (tableName.isEmpty()) {
|
||||
return ValidationResult.error(entityClass.getSimpleName(), "@TableName 注解值为空");
|
||||
}
|
||||
|
||||
// 检查表是否存在
|
||||
if (!isTableExists(tableName)) {
|
||||
return ValidationResult.error(entityClass.getSimpleName(),
|
||||
"数据库表不存在: " + tableName);
|
||||
}
|
||||
|
||||
List<String> dbColumns = getTableColumns(tableName);
|
||||
List<EntityFieldInfo> entityFields = getEntityFields(entityClass);
|
||||
|
||||
// 对比字段映射
|
||||
List<String> missingInEntity = findMissingInEntity(dbColumns, entityFields);
|
||||
List<String> missingInDb = findMissingInDatabase(entityFields, dbColumns);
|
||||
List<String> typeMismatches = findTypeMismatches(entityClass, tableName, entityFields, dbColumns);
|
||||
|
||||
return ValidationResult.of(entityClass.getSimpleName(), tableName,
|
||||
missingInEntity, missingInDb, typeMismatches);
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描包下的所有实体类
|
||||
*/
|
||||
private Set<Class<?>> findEntitiesInPackage(String basePackage) {
|
||||
Set<Class<?>> entities = new LinkedHashSet<>();
|
||||
try {
|
||||
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
|
||||
ClassUtils.convertClassNameToResourcePath(basePackage) + "/**/*.class";
|
||||
|
||||
Resource[] resources = resourcePatternResolver.getResources(packageSearchPath);
|
||||
|
||||
for (Resource resource : resources) {
|
||||
if (resource.isReadable()) {
|
||||
try {
|
||||
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
|
||||
String className = metadataReader.getClassMetadata().getClassName();
|
||||
|
||||
// 过滤内部类、匿名类等
|
||||
if (className.contains("$")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Class<?> clazz = Class.forName(className);
|
||||
if (clazz.isAnnotationPresent(TableName.class)) {
|
||||
entities.add(clazz);
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
log.warn("无法加载类: {}", resource.getFilename());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("扫描包 {} 失败: {}", basePackage, e.getMessage());
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库表的所有字段
|
||||
*/
|
||||
private List<String> getTableColumns(String tableName) {
|
||||
return tableColumnsCache.computeIfAbsent(tableName, this::fetchTableColumnsFromDb);
|
||||
}
|
||||
|
||||
private List<String> fetchTableColumnsFromDb(String tableName) {
|
||||
List<String> columns = new ArrayList<>();
|
||||
try (Connection conn = dataSource.getConnection()) {
|
||||
DatabaseMetaData metaData = conn.getMetaData();
|
||||
|
||||
// 尝试不同的表名匹配策略
|
||||
ResultSet rs = metaData.getColumns(null, null, tableName, null);
|
||||
if (!rs.next()) {
|
||||
// 尝试小写
|
||||
rs = metaData.getColumns(null, null, tableName.toLowerCase(), null);
|
||||
}
|
||||
if (!rs.next()) {
|
||||
// 尝试大写
|
||||
rs = metaData.getColumns(null, null, tableName.toUpperCase(), null);
|
||||
}
|
||||
|
||||
// 重置游标
|
||||
rs.beforeFirst();
|
||||
|
||||
while (rs.next()) {
|
||||
String columnName = rs.getString("COLUMN_NAME");
|
||||
// 清理列名中的特殊字符
|
||||
columnName = cleanColumnName(columnName);
|
||||
columns.add(columnName.toLowerCase());
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.error("获取表 {} 字段失败: {}", tableName, e.getMessage());
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查表是否存在
|
||||
*/
|
||||
private boolean isTableExists(String tableName) {
|
||||
try (Connection conn = dataSource.getConnection()) {
|
||||
DatabaseMetaData metaData = conn.getMetaData();
|
||||
ResultSet rs = metaData.getTables(null, null, tableName, null);
|
||||
if (rs.next()) return true;
|
||||
|
||||
// 尝试小写
|
||||
rs = metaData.getTables(null, null, tableName.toLowerCase(), null);
|
||||
if (rs.next()) return true;
|
||||
|
||||
// 尝试大写
|
||||
rs = metaData.getTables(null, null, tableName.toUpperCase(), null);
|
||||
return rs.next();
|
||||
|
||||
} catch (SQLException e) {
|
||||
log.error("检查表是否存在失败: {}", e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取实体类的所有字段信息
|
||||
*/
|
||||
private List<EntityFieldInfo> getEntityFields(Class<?> entityClass) {
|
||||
List<EntityFieldInfo> fields = new ArrayList<>();
|
||||
Class<?> currentClass = entityClass;
|
||||
|
||||
// 遍历所有父类直到 Object
|
||||
while (currentClass != null && currentClass != Object.class) {
|
||||
Field[] declaredFields = currentClass.getDeclaredFields();
|
||||
|
||||
for (Field field : declaredFields) {
|
||||
// 忽略静态字段、序列化字段等
|
||||
if (shouldIgnoreField(field)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
EntityFieldInfo fieldInfo = extractFieldInfo(field);
|
||||
if (fieldInfo != null) {
|
||||
fields.add(fieldInfo);
|
||||
}
|
||||
}
|
||||
|
||||
currentClass = currentClass.getSuperclass();
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否应该忽略该字段
|
||||
*/
|
||||
private boolean shouldIgnoreField(Field field) {
|
||||
int modifiers = field.getModifiers();
|
||||
|
||||
// 忽略静态字段
|
||||
if (Modifier.isStatic(modifiers)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 忽略序列化字段
|
||||
if ("serialVersionUID".equals(field.getName())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 忽略被 @TableField(exist = false) 标记的字段
|
||||
TableField tableField = field.getAnnotation(TableField.class);
|
||||
if (tableField != null && !tableField.exist()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 提取字段信息
|
||||
*/
|
||||
private EntityFieldInfo extractFieldInfo(Field field) {
|
||||
String fieldName = field.getName();
|
||||
String columnName;
|
||||
|
||||
TableField tableField = field.getAnnotation(TableField.class);
|
||||
if (tableField != null && !tableField.value().isEmpty()) {
|
||||
columnName = tableField.value();
|
||||
} else {
|
||||
columnName = StrUtil.toUnderlineCase(fieldName);
|
||||
}
|
||||
|
||||
// 清理列名中的特殊字符
|
||||
columnName = cleanColumnName(columnName);
|
||||
|
||||
return new EntityFieldInfo(
|
||||
fieldName,
|
||||
columnName.toLowerCase(),
|
||||
field.getType().getSimpleName()
|
||||
);
|
||||
}
|
||||
/**
|
||||
* 清理列名,处理各种特殊情况
|
||||
*/
|
||||
private String cleanColumnName(String columnName) {
|
||||
if (columnName == null || columnName.isEmpty()) {
|
||||
return columnName;
|
||||
}
|
||||
|
||||
// 去掉反引号、单引号、双引号等
|
||||
columnName = columnName.replace("`", "")
|
||||
.replace("'", "")
|
||||
.replace("\"", "")
|
||||
.trim();
|
||||
|
||||
// 如果列名被方括号包围(SQL Server风格),去掉方括号
|
||||
if (columnName.startsWith("[") && columnName.endsWith("]")) {
|
||||
columnName = columnName.substring(1, columnName.length() - 1);
|
||||
}
|
||||
|
||||
return columnName;
|
||||
}
|
||||
/**
|
||||
* 找出数据库中有的但实体类缺少的字段
|
||||
*/
|
||||
private List<String> findMissingInEntity(List<String> dbColumns, List<EntityFieldInfo> entityFields) {
|
||||
Set<String> entityColumnNames = entityFields.stream()
|
||||
.map(EntityFieldInfo::getColumnName)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
return dbColumns.stream()
|
||||
.filter(column -> !entityColumnNames.contains(column))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 找出实体类有的但数据库缺少的字段
|
||||
*/
|
||||
private List<String> findMissingInDatabase(List<EntityFieldInfo> entityFields, List<String> dbColumns) {
|
||||
Set<String> dbColumnSet = new HashSet<>(dbColumns);
|
||||
|
||||
return entityFields.stream()
|
||||
.map(EntityFieldInfo::getColumnName)
|
||||
.filter(columnName -> !dbColumnSet.contains(columnName))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 找出类型不匹配的字段(基础实现)
|
||||
*/
|
||||
private List<String> findTypeMismatches(Class<?> entityClass, String tableName,
|
||||
List<EntityFieldInfo> entityFields, List<String> dbColumns) {
|
||||
// 这里可以实现更复杂的类型匹配检查
|
||||
// 目前返回空列表,可以根据需要扩展
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印验证摘要
|
||||
*/
|
||||
public void printValidationSummary(Map<String, ValidationResult> results) {
|
||||
if (results.isEmpty()) {
|
||||
log.info("🎉 没有找到需要验证的实体类!");
|
||||
return;
|
||||
}
|
||||
|
||||
long errorCount = results.values().stream()
|
||||
.filter(ValidationResult::hasIssues)
|
||||
.count();
|
||||
long successCount = results.size() - errorCount;
|
||||
|
||||
log.info("验证完成!总计验证 {} 个实体类,成功: {},存在问题: {}",
|
||||
results.size(), successCount, errorCount);
|
||||
|
||||
if (errorCount == 0) {
|
||||
log.info("🎉 所有实体类映射验证通过!");
|
||||
return;
|
||||
}
|
||||
|
||||
log.warn("⚠️ 发现 {} 个实体类存在映射问题:", errorCount);
|
||||
|
||||
results.forEach((className, result) -> {
|
||||
if (result.hasIssues()) {
|
||||
log.warn("\n==========================================");
|
||||
log.warn("实体类: {} -> 表: {}", className, result.getTableName());
|
||||
|
||||
if (!result.getMissingInEntity().isEmpty()) {
|
||||
log.warn("❌ 数据库有但实体缺少: {}", result.getMissingInEntity());
|
||||
}
|
||||
|
||||
if (!result.getMissingInDb().isEmpty()) {
|
||||
log.warn("❌ 实体有但数据库缺少: {}", result.getMissingInDb());
|
||||
}
|
||||
|
||||
if (!result.getTypeMismatches().isEmpty()) {
|
||||
log.warn("⚠️ 类型不匹配: {}", result.getTypeMismatches());
|
||||
}
|
||||
|
||||
if (result.getError() != null) {
|
||||
log.warn("💥 验证错误: {}", result.getError());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
log.warn("\n==========================================");
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成详细的验证报告
|
||||
*/
|
||||
public String generateDetailedReport() {
|
||||
Map<String, ValidationResult> results = validateAllEntitiesInProject();
|
||||
|
||||
StringBuilder report = new StringBuilder();
|
||||
report.append("实体类映射验证报告\n");
|
||||
report.append("生成时间: ").append(new Date()).append("\n\n");
|
||||
|
||||
if (results.isEmpty()) {
|
||||
report.append("✅ 没有找到需要验证的实体类\n");
|
||||
return report.toString();
|
||||
}
|
||||
|
||||
long errorCount = results.values().stream()
|
||||
.filter(ValidationResult::hasIssues)
|
||||
.count();
|
||||
long successCount = results.size() - errorCount;
|
||||
|
||||
report.append("验证统计: 总计 ").append(results.size())
|
||||
.append(" 个实体类,成功: ").append(successCount)
|
||||
.append(",存在问题: ").append(errorCount).append("\n\n");
|
||||
|
||||
if (errorCount == 0) {
|
||||
report.append("✅ 所有实体类映射正确\n");
|
||||
return report.toString();
|
||||
}
|
||||
|
||||
report.append("发现 ").append(errorCount).append(" 个问题:\n\n");
|
||||
|
||||
results.forEach((className, result) -> {
|
||||
if (result.hasIssues()) {
|
||||
report.append("实体类: ").append(className)
|
||||
.append(" -> 表: ").append(result.getTableName()).append("\n");
|
||||
|
||||
if (!result.getMissingInEntity().isEmpty()) {
|
||||
report.append(" 数据库有但实体缺少: ").append(result.getMissingInEntity()).append("\n");
|
||||
}
|
||||
|
||||
if (!result.getMissingInDb().isEmpty()) {
|
||||
report.append(" 实体有但数据库缺少: ").append(result.getMissingInDb()).append("\n");
|
||||
}
|
||||
|
||||
if (!result.getTypeMismatches().isEmpty()) {
|
||||
report.append(" 类型不匹配: ").append(result.getTypeMismatches()).append("\n");
|
||||
}
|
||||
|
||||
if (result.getError() != null) {
|
||||
report.append(" 错误: ").append(result.getError()).append("\n");
|
||||
}
|
||||
|
||||
report.append("\n");
|
||||
}
|
||||
});
|
||||
|
||||
return report.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取验证统计信息
|
||||
*/
|
||||
public Map<String, Object> getValidationStatistics() {
|
||||
Map<String, ValidationResult> results = validateAllEntitiesInProject();
|
||||
|
||||
long total = results.size();
|
||||
long errorCount = results.values().stream()
|
||||
.filter(ValidationResult::hasIssues)
|
||||
.count();
|
||||
long successCount = total - errorCount;
|
||||
|
||||
Map<String, Object> stats = new HashMap<>();
|
||||
stats.put("totalEntities", total);
|
||||
stats.put("successCount", successCount);
|
||||
stats.put("errorCount", errorCount);
|
||||
stats.put("successRate", total > 0 ? (successCount * 100.0 / total) : 0);
|
||||
stats.put("lastValidated", new Date());
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package com.zhgd.xmgl.modules.validator;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 实体字段信息类
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
class EntityFieldInfo {
|
||||
private String fieldName;
|
||||
private String columnName;
|
||||
private String fieldType;
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
package com.zhgd.xmgl.modules.validator;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@RestController
|
||||
@RequestMapping("/xmgl/entity-validator")
|
||||
public class EntityValidatorController {
|
||||
|
||||
@Autowired
|
||||
private BulkEntityValidator validator;
|
||||
|
||||
@GetMapping("/validate-all")
|
||||
public Map<String, Object> validateAll() {
|
||||
Map<String, ValidationResult> results = validator.validateAllEntitiesInProject();
|
||||
|
||||
long errorCount = results.values().stream()
|
||||
.filter(ValidationResult::hasIssues)
|
||||
.count();
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("totalEntities", results.size());
|
||||
response.put("errorCount", errorCount);
|
||||
response.put("successCount", results.size() - errorCount);
|
||||
response.put("results", results);
|
||||
response.put("report", validator.generateDetailedReport());
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@PostMapping("/validate-package")
|
||||
public Map<String, Object> validatePackage(@RequestParam String packageName) {
|
||||
Map<String, ValidationResult> results = validator.validatePackageEntities(packageName);
|
||||
|
||||
long errorCount = results.values().stream()
|
||||
.filter(ValidationResult::hasIssues)
|
||||
.count();
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("package", packageName);
|
||||
response.put("totalEntities", results.size());
|
||||
response.put("errorCount", errorCount);
|
||||
response.put("successCount", results.size() - errorCount);
|
||||
response.put("results", results);
|
||||
response.put("hasIssues", errorCount > 0);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@GetMapping("/status")
|
||||
public Map<String, Object> getValidationStatus() {
|
||||
return validator.getValidationStatistics();
|
||||
}
|
||||
|
||||
@GetMapping("/report")
|
||||
public String getDetailedReport() {
|
||||
return validator.generateDetailedReport();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package com.zhgd.xmgl.modules.validator;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 验证结果类
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
class ValidationResult {
|
||||
private String className;
|
||||
private String tableName;
|
||||
private List<String> missingInEntity;
|
||||
private List<String> missingInDb;
|
||||
private List<String> typeMismatches;
|
||||
private String error;
|
||||
|
||||
public static ValidationResult of(String className, String tableName,
|
||||
List<String> missingInEntity, List<String> missingInDb,
|
||||
List<String> typeMismatches) {
|
||||
return new ValidationResult(className, tableName, missingInEntity, missingInDb, typeMismatches, null);
|
||||
}
|
||||
|
||||
public static ValidationResult error(String className, String error) {
|
||||
return new ValidationResult(className, null, Collections.emptyList(),
|
||||
Collections.emptyList(), Collections.emptyList(), error);
|
||||
}
|
||||
|
||||
public boolean hasIssues() {
|
||||
return error != null ||
|
||||
!missingInEntity.isEmpty() ||
|
||||
!missingInDb.isEmpty() ||
|
||||
!typeMismatches.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
package com.zhgd.xmgl.modules.validator;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class ValidatorConfig {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public BulkEntityValidator bulkEntityValidator() {
|
||||
return new BulkEntityValidator();
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user