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

news2024/11/26 13:55:41

需求:使用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导入逻辑省略,参考官方文档即可。

最终效果:


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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2124661.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JAVA基础】实现Tomcat基本功能

文章目录 TCP/IP协议Socket编程ServletTomcat 在搜索了两三天之后&#xff0c;也是大概弄懂了Tomcat是个什么东西&#xff0c;我们在说Tomcat之前&#xff0c;先来了解一下下面这三个东西&#xff1a; TCP/IP协议 TCP/IP 是互联网通信的基础协议。TCP&#xff08;传输控制协议…

C++类和对象3

一.初始化列表 我们之前的构造函数都是在函数体内对数据成员进行赋值 Date(int year, int month, int day) {_year year;_month month;_day day; } 然而我们的构造函数还有另一种初始化的方式&#xff1a;初始化列表 ——初始化列表是以参数表后冒号开始&#xff0c;用数…

数学建模笔记—— 多目标规划

数学建模笔记—— 多目标规划 多目标规划1. 模型原理1.1 多目标规划的一般形式1.2 多目标规划的解1.3 多目标规划的求解 2. 典型例题3. matlab代码实现 多目标规划 多目标规划是数学规划的一个分支。研究多于一个的目标函数在给定区域上的最优化。又称多目标最优化。通常记为 …

VCS(Video Cloud Storage)解决方案研究报告

1.背景 控视频是重要的数据资产和证据链&#xff0c;在银行、交通、司法等行业对视频数据有很高的安全等级。随着监控的重要性不断提升&#xff0c;在能源、电力、校园、厂矿、高星酒店等多场景中对监控存储也有更高要求&#xff0c;体现为海量存储、超长时间和数据安全。为了充…

得物APP助力释放首发经济新活力,解锁年轻潮流密码

在消费升级与高质量发展的时代背景下&#xff0c;我国首发经济正以前所未有的活力蓬勃发展&#xff0c;成为推动市场繁荣、满足个性化消费需求的重要力量。首发&#xff0c;即产品首次在市场亮相&#xff0c;往往代表着最新的设计理念、最尖端的科技应用以及最前沿的潮流趋势。…

C++入门知识(1)

一、namespace 1、用处 可以解决程序里面定义重名变量的问题 namespace是一个命名空间。 定义变量可以在4个域下面定义&#xff0c;全局域&#xff0c;局部域&#xff0c;命名空间域&#xff0c;类域。各个域之间是相互不影响的。命名空间里面的变量可以和外面的变量重名 2…

Stable Diffusion4.9一键安装教程SD(AI绘画软件)

**无套路&#xff01;**文末提供下载方式 Stable Diffusion 是一款革命性的 AI 绘画生成工具&#xff0c;它通过潜在空间扩散模型&#xff0c;将图像生成过程转化为一个逐步去噪的“扩散”过程。 与传统的高维图像空间操作不同&#xff0c;Stable Diffusion 首先将图像压缩到…

样品管理的重要性与实操解决方案,外贸软件一键搞定

在外贸过程中&#xff0c;样品管理是一个重要的环节&#xff0c;它不仅涉及到产品的质量和细节确认&#xff0c;还是与客户沟通的重要桥梁。在选择客户时&#xff0c;通常会优先考虑那些目的明确、意向较强的客户&#xff0c;因为这些客户成交的可能性较大。无论是纺织品、服装…

基于SpringBoot+Vue的学生成绩管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的学生成绩…

Python语法,从入门到精通,一步到位!

Python语法及入门涵盖了多个方面&#xff0c;包括基本语法、数据类型、控制流、函数、模块等。以下是一个超全超详细的介绍&#xff1a; 一、Python基本语法 注释&#xff1a;Python中使用井号&#xff08;#&#xff09;表示注释&#xff0c;从井号开始到行尾的内容都会被Pytho…

一节课教你学会【预处理详解】

谢谢观看&#xff01;希望以下内容帮助到了你&#xff0c;对你起到作用的话&#xff0c;可以一键三连加关注&#xff01;你们的支持是我更新地动力。 因作者水平有限&#xff0c;有错误还请指出&#xff0c;多多包涵&#xff0c;谢谢&#xff01; 预处理详解 一、预定义符号二、…

红米K60U/K50/Note11TPro澎湃OS无法绑定账号解锁BL-不能激活小米账号

小米澎湃OS对于解锁BL&#xff0c;新增了各种限制&#xff0c;早前我们还能使用bypass脚本来实现澎湃OS上绑 定账号成功&#xff0c;但随着澎湃OS七月系统上的推送&#xff0c;旧版的bypass已经彻底失效&#xff0c;并且无法安装 旧版的设置APK来解决问题。此次涉及的机型有红米…

SpringSecurity剖析

1、SpringSecurity 入门 1.1、简介 Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它是用于保护基于Spring的应用程序的实际标准。Spring Security是一个框架&#xff0c;致力于为Java应用程序提供身份验证和授权。与所有Spring项目一样&#xff0c;Sp…

【PX4-AutoPilot教程-TIPS】PX4中MAVLink话题频率修改

PX4中MAVLink话题频率修改 方法一&#xff1a;使用QGC地面站通过命令行解释器MAVLink Shell修改话题频率方法二&#xff1a;使用SD卡中的命令脚本文件修改话题频率方法三&#xff1a;通过修改PX4飞控固件源码修改话题频率 环境&#xff1a; PX4 &#xff1a;1.13.0 方法一&am…

SOP流程制定:vioovi ECRS工时分析软件的智慧引领

在现代制造业中&#xff0c;标准化操作流程&#xff08;SOP&#xff09;已成为提升生产效率、确保产品质量、降低运营成本的关键要素。SOP不仅为生产活动提供了明确的指导&#xff0c;还促进了企业管理的规范化和精细化。然而&#xff0c;如何科学、高效地制定SOP流程&#xff…

CISC 和 RISC 架构的对比

研究 RISC 架构优缺点的最简单方法是将其与其前身进行对比&#xff1a; CISC&#xff08;复杂指令集计算机&#xff09;架构。 内存中的两个数字相乘 右图表示一台普通计算机的存储方案。 主存储器被划分为编号从&#xff08;行&#xff09;1&#xff1a;&#xff08;列&…

RAG系统的7个检索指标:信息检索任务准确性评估指南

大型语言模型&#xff08;LLMs&#xff09;作为一种生成式AI技术&#xff0c;在近两年内获得了显著的关注和应用。但是在实际部署中&#xff0c;LLMs的知识局限性和幻觉问题仍然是一个挑战。检索增强生成&#xff08;Retrieval Augmented Generation&#xff0c;RAG&#xff09…

好网站包含哪些方面

好网站通常在多个方面都表现出色&#xff0c;包括但不限于设计、内容、导航、性能和互动性。下面将详细介绍这些方面。 首先&#xff0c;设计是一个网站吸引用户的第一印象。一个好的网站设计应该是清晰、直观、美观&#xff0c;并且符合用户体验原则。页面布局应该合理&#x…

Spire.PDF for .NET【文档操作】演示:创比较 PDF 文档

PDF 已成为跨不同平台共享和保存文档的标准格式&#xff0c;在专业和个人环境中都发挥着无处不在的作用。但是&#xff0c;创建高质量的 PDF 文档需要多次检查和修订。在这种情况下&#xff0c;了解如何有效地比较 PDF 文件并找出它们的差异变得至关重要&#xff0c;这使文档编…

【Go】Go语言基本语法--注释、变量、常量

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…