Java中校验导入字段长度与数据库字段长度一致性

需求:使用EasyExcel导入数据时,根据数据库字段长度校验导入字段的长度。使用的数据库是mysql。若是一般的校验需求, Spring Validation 或 Hibernate Validator 即可满足。

实现步骤:

  • 获取需要校验的表,查询出字段相关信息
  • 对比导入字段与数据库字段长度,不符合则跑出异常
  • 实体字段的属性应该与数据库字段对应的驼峰命名相同,如数据库是user_age, 实体属性应是userAge;
  • 只校验字符串类型的字段

代码示例

数据库字段信息类:

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * @author sjy
 * @date 2024/9/4 17:59
 * @description:
 */
@Data
public class DatabaseInfoVo {

    @ApiModelProperty("表名")
    private String tableName;

    @ApiModelProperty("列名")
    private String columnName;

    @ApiModelProperty("字段注释")
    private String comment;

    @ApiModelProperty("字段长度")
    private Integer length;
}

xml查询语句示例:

<select id="findDatabaseSchemaInfo" resultType="xxxxx.vo.DatabaseInfoVo">
  SELECT
  TABLE_NAME AS tableName,
  COLUMN_NAME AS columnName,
  COLUMN_COMMENT AS comment,
  CHARACTER_MAXIMUM_LENGTH AS length
  FROM
  INFORMATION_SCHEMA.COLUMNS
  WHERE
  TABLE_SCHEMA = #{useDbname}
  AND TABLE_NAME in ('yourtable','yourtable','yourtable','yourtable','yourtable')
  AND CHARACTER_MAXIMUM_LENGTH IS NOT NULL
  AND COLUMN_NAME NOT IN ('KSKID','KSJCXXID')
</select>

这里只需要校验固定的几张表,想要灵活的话可以修改成参数传递进来。

对比逻辑:

private final ThreadLocal<Map<String, DatabaseInfoVo>> databaseInfoLocal = new ThreadLocal<>();
// 使用完成需要释放
public void removeThreadLocal() {
        databaseInfoLocal.remove();
    }
	/**
     * 校验导入字段值与数据库字段值长度
     * @param dto
     */
    private void validDatabaseWord (yourDto dto) {
        Map<String, DatabaseInfoVo> databaseInfoVoMap = databaseInfoLocal.get();
        if (CollectionUtils.isEmpty(databaseInfoVoMap)) {
            List<DatabaseInfoVo> databaseSchemaInfoList = yourmapper.findDatabaseSchemaInfo(useDbname);
            if (databaseSchemaInfoList != null) {
                databaseInfoVoMap = databaseSchemaInfoList.stream()
                        .filter(databaseInfoVo ->
                                // xx表只需要校验两个字段
                                !"table".equals(databaseInfoVo.getTableName()) ||
                                        "column1".equals(databaseInfoVo.getColumnName()) ||
                                        "column2".equals(databaseInfoVo.getColumnName()))
                        .collect(Collectors.toMap(
                                databaseInfoVo -> toCamelCase(databaseInfoVo.getColumnName()),
                                databaseInfoVo -> databaseInfoVo,
                                (existing, replacement) -> existing // 处理键冲突时保留现有的值
                        ));
            } else {
                databaseInfoVoMap = Maps.newHashMap();
            }
            databaseInfoLocal.set(databaseInfoVoMap);
        }

        // 获取实体的属性
        Field[] fields = yourDto.class.getDeclaredFields();
        for (Field field : fields) {
            // 仅处理String类型的属性
            if (field.getType().equals(String.class)) {
                // 允许访问私有字段
                field.setAccessible(true);
                String fieldName = field.getName();
                if (databaseInfoVoMap.containsKey(fieldName)) {
                    DatabaseInfoVo databaseInfo = databaseInfoVoMap.get(fieldName);
                    if (ObjectUtil.isNotNull(databaseInfo)) {
                        // 获取数据库列的长度
                        int dbColumnLength = databaseInfo.getLength();
                        try {
                            // 获取实体属性的值
                            Object fieldValue = field.get(dto);
                            if (fieldValue != null) {
                                String value = (String) fieldValue;
                                if (value.length() > dbColumnLength) {
                                    // 如果没有引入swagger,直接使用列描述即可
                                    // throw new CheckedException(databaseInfo.getComment() + "超过长度,最大长度:" + databaseInfo.getLength());
                                    ApiModelProperty apiModelProperty = field.getAnnotation(ApiModelProperty.class);
                                    String apiPropertyValue = apiModelProperty.value();
                                    // 执行处理逻辑,例如截断、抛出异常、记录日志等
                                    throw new CheckedException(apiPropertyValue + "超过长度,最大长度:" + databaseInfo.getLength());
                                }
                            }
                        } catch (IllegalAccessException e) {
                            // 处理访问异常
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    /**
     * 数据库字段转驼峰
     * @param word
     * @return
     */
    public String toCamelCase(String word) {
        if (StrUtil.isAllBlank(word)) {
            return "";
        }
        StringBuilder result = new StringBuilder();
        boolean toUpperCase = false;

        for (char ch : word.toCharArray()) {
            if (ch == '_') {
                toUpperCase = true;
            } else {
                if (toUpperCase) {
                    result.append(Character.toUpperCase(ch));
                    toUpperCase = false;
                } else {
                    result.append(Character.toLowerCase(ch));
                }
            }
        }
        return result.toString();
    }

Easyexcel导入逻辑省略,参考官方文档即可。

最终效果:


生命可以随心所欲,但不能随波逐流。 – 宫崎骏

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值