异常信息

exception.ServiceException: com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 'XXX' at row 1

问题

代码运行发现有一行报警,很明显可以判断字段插入内容超过表结构设置的长度了。不过比较奇怪的是,为什么测试环境一直没测试出来呢,难道是测试和线上环境Mysql配置不同?咨询了dba,得到的反馈是一致的。

分析

首先可以确定的是测试环境和线上表单是一致的,因此排除字段长度不一致的原因。

然后怀疑是否是测试环境有什么配置导致插入时会自动截断?

1、捷径,先搜索关键字“mysql设置插入超长自动截断”

发现mysql的sql_mode:

mysql支持的sql_mode模式:ANSI、TRADITIONAL、STRICT_ALL_TABLES和STRICT_TRANS_TABLES。

ANSI模式:宽松模式,对插入数据进行校验,如果不符合定义类型或长度,对数据类型调整或截断保存,报warning警告。

TRADITIONAL模式:严格模式,当向mysql数据库插入数据时,进行数据的严格校验,保证错误数据不能插入,报error错误。用于事物时,会进行事物的回滚。

STRICT_TRANS_TABLES模式:严格模式,进行数据的严格校验,错误数据不能插入,报error错误。只对支持事务的表有效。

STRICT_ALL_TABLES模式:严格模式,进行数据的严格校验,错误数据不能插入,报error错误。对所有表都有效。

测试了命令行插入超长字段内容,确实是有warning,但是插入成功了。也就是说我所执行的命令行默认是ANSI模式的,所以只报了warning

难道是代码运行时jdbc设置了严格模式?

2、查源码

首先根据错误位置

找到对应位置

看下xopen哪来的

    public final static int ER_DATA_TOO_LONG = 1406; //SQLSTATE: 22001 Message: Data too long for column '%s' at row %ld
...
public static final String SQL_STATE_STRING_DATA_RIGHT_TRUNCATION = "22001";
...
  mysqlToSqlState.put(MysqlErrorNumbers.ER_DATA_TOO_LONG, SQL_STATE_STRING_DATA_RIGHT_TRUNCATION);

具体源码不展开,基本可以看到先从mysql返回了一个1406的ERROR SQLSTATE,然后转译成了22,进行错误判断,后抛出MysqlDataTruncation异常。

注意到,这里是ERROR,也就是说jdbc的sql_mode应该是严格模式,搜索下,发现以下代码:

    private void setupServerForTruncationChecks() throws SQLException {
if (getJdbcCompliantTruncation()) {
if (versionMeetsMinimum(5, 0, 2)) {
String currentSqlMode = this.serverVariables.get("sql_mode"); boolean strictTransTablesIsSet = StringUtils.indexOfIgnoreCase(currentSqlMode, "STRICT_TRANS_TABLES") != -1; if (currentSqlMode == null || currentSqlMode.length() == 0 || !strictTransTablesIsSet) {
StringBuffer commandBuf = new StringBuffer("SET sql_mode='"); if (currentSqlMode != null && currentSqlMode.length() > 0) {
commandBuf.append(currentSqlMode);
commandBuf.append(",");
} commandBuf.append("STRICT_TRANS_TABLES'"); execSQL(null, commandBuf.toString(), -1, null, DEFAULT_RESULT_SET_TYPE, DEFAULT_RESULT_SET_CONCURRENCY, false, this.database, null, false); setJdbcCompliantTruncation(false); // server's handling this for us now
} else if (strictTransTablesIsSet) {
// We didn't set it, but someone did, so we piggy back on it
setJdbcCompliantTruncation(false); // server's handling this for us now
} }
}
}

可以看到,默认设置了严格模式,终于破案了。

这个问题遇到后,事先知道有这么一个坑,以后如果遇到命令行可以执行,而jdbc执行报错的问题,就可以道出原因了。另外命令行也可以设置sql_mode,这样二者就一致了。

set sql_mode='STRICT_TRANS_TABLES';

验证结果:

Mysql命令行插入字段超长不报错,而jdbc报错问题分析的更多相关文章

  1. Mysql命令行改动字段类型

    在做微信公众平台 知识百科(账号:zhishiwiki) 时,由于字段先前设计的不合理.导致内容装不下,因此须要改动其字段类型为 text 这里使用到了 alter 命令 alter table 表名 ...

  2. mysql命令行以及mysql workbence查询结果中文乱码的解决方法

    最近正在学习mysql,安装环境是windows server 2003 32位操作系统+mysql 5.1.47同时也安装了mysql命令行以及mysql workbench这里是test数据库cr ...

  3. 使用mysql 命令行,增加 ,删除 字段 并 设置默认值 及 非空

    使用mysql 命令行,增加 ,删除 字段 并 设置默认值 及 非空 添加 alter table table_name add field_name field_type; 添加,并设置默认值,及非 ...

  4. mysql命令行批量插入100条数据命令

    先介绍一个关键字的使用: delimiter 定好结束符为"$$",(定义的时候需要加上一个空格) 然后最后又定义为";", MYSQL的默认结束符为" ...

  5. [转]Mysql命令行常用操作

    Mysql命令行常用操作 一.从命令行登录MySQL数据库服务器 1.登录使用默认3306端口的MySQL /usr/local/mysql/bin/mysql -u root -p 2.通过TCP连 ...

  6. MySql命令行命令和SQL语句

    一.常用mysql命令行命令 1.启动MYSQL服务 net start mysql 停止MYSQL服务 net stop mysql 2.netstat -na|findstr 3306 查看被监听 ...

  7. 如何使用mysql命令行

    现在向大家介绍mysql命令行下,从数据库的建立到表数据的删除全过程,希望对网友有所帮助 方法/步骤 1.登陆mysql 打cmd命令终端,如果已经添加了mysql的环境变量,可以直接使用命令 mys ...

  8. Mysql命令行导入sql数据

    mysqldump  是在  操作系统命令行下运行的,不是在 MySQL 命令行下运行的. 登陆数据库: 登陆本地mysql : mysql -h localhost -u root -p123456 ...

  9. [MySQL]命令行工具和基本操作

    [MySQL]命令行工具和基本操作 一 MySQL命令行工具  (查看帮助 ---help,或 -?) 1)MySQL MySQL是一个简单的SQL外壳(有GNU readline功能).它支持交互式 ...

随机推荐

  1. 关于 video 播放的新探索

    前端同学要使用 HTML5 播放器视频,必然会使用 video 标签,不过大多数同学只是使用了较简单的功能,其实它本身拥有不凡之力有待我们发现. 首先,我们先来看下 video 最基础的用法: 使用 ...

  2. python-正整数的因子展开式

    [题目描述]编写程序,输出一个给定正整数x(x>1)的质因子展开式. [输入格式]请在一行中输入整数x的值. [输出格式]对每一组输入的x,按以下格式输出x的质因子展开式(假如x的质因子分别为a ...

  3. java中如何打印规定图案? 举例说明

    9.4 print out the following pattern(打印图案). * *** ***** ******* ***** *** * 提示: 1)本题上面的图案和下面的图案是一样的.所 ...

  4. YACS-2022.4-银组

    https://www.iai.sh.cn/contest 2022.04 银组,理论上 \(100+100+30+100\). T1 上锁的抽屉 题目描述 有一个抽屉柜里竖排了 \(n\) 只抽屉. ...

  5. Shiro之权限管理的概念

    文章目录 前言:什么是shiro 一.什么是权限管理? 举例 二.权限管理的具体分类 1.身份认证 2.授权 总结 前言:什么是shiro Apache Shiro 是一个开源安全框架,提供身份验证. ...

  6. 企业需要使用网络损伤仪 WANsim 的帮助,以便更高效地迁移到云端

    正确解决与云环境中的应用程序部署有关的问题需要针对每个系统的独特需求以寻找特定的网络工具.网络损伤仪 WANsim 助力企业更高效地迁移到云端! 起初,云厂商以在云端办公相对于传统方式拥有更高的可靠性 ...

  7. Spring Boot 使用 Redis 共享 Session 代码示例

    参考资料 博客:spring boot + redis 实现session共享 1. 新建 Maven 工程 我新建 spring-boot-session-redis maven 工程 2. 引入 ...

  8. SpringMVC快速使用——基于XML配置和Servlet3.0

    SpringMVC快速使用--基于XML配置和Servlet3.0 1.官方文档 https://docs.spring.io/spring-framework/docs/5.2.8.RELEASE/ ...

  9. python3拉勾网爬虫之(您操作太频繁,请稍后访问)

    你是否经历过这个:那就对了~因为需要post和相关的cookie来请求~所以,一个简单的代码爬拉钩~~~

  10. linux find命令 -mtime参数 根据修改时间查找文件

    命令:find 搜索路径 -mtime n 主要说明n的含义: 例: n=5 "5"指的是前 5~6 天那一天修改的文件 n=-5 "-5"指的是 5 天内修改 ...