异常信息

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. 面试题:给你个id,去拿到name,多叉树遍历

    前天面试遇到一个多叉树面试的题目,在这里分享记录一下. 题目:一个树形的数据(如下数据),面试官给你一个id,然后拿到对应的name? 数据结构大概是这个样子 var cityData = [ { i ...

  2. AS修改text内容+显示不同页面

    新创建一个project,命名为myclass. 一:修改 在res中找到layout打开xml文件,右上角有一个code,点击进入可以写代码的文件,并在里面进行修改.(老版本写代码的界面在下面与de ...

  3. java中如何能把一个字符串转成日期对象

    题目3.1: 把一个字符串转成日期对象 当我们想根据输入字符串得到一个日期对象时我们不知道,应该以什么格式写这个字符串,才能被系统正确解析,一种聪明的做法是,马克-to-win,我们先 把日期对象根据 ...

  4. java中Number Type Casting(数字类型强转)的用法

    4.5 Number Type Casting(数字类型强转)隐式 casting(from small to big) byte a = 111; int b = a;显式 casting(from ...

  5. HashMap和ConcurrentHashMap的原理和实现

    一.线程不安全的HashMap 多线程环境下,使用HashMap进行put操作会引起死循环(jdk1.7 Entry链表形成环形数据结构),导致CPU利用率接近100%. 结构:数组 table[]+ ...

  6. FreeRTOS学习记录--任务创建函数详解

    开局一张图.一步一步分析就好. (一)什么是任务? 在多任务系统中,我们按照功能不同,把整个系统分割成一个个独立的,且无法返回的函数,这个函数我们称为任务:任务包含几个属性:任务堆栈,任务函数.任务控 ...

  7. 实战-DRF快速写接口(认证权限频率)

    实战-DRF快速写接口 开发环境 Python3.6 Pycharm专业版2021.2.3 Sqlite3 Django 2.2 djangorestframework3.13 测试工具 Postma ...

  8. 小程序容器助力打造企业超级App

    阿拉丁研究院发布<2021 年度小程序互联网发展白皮书>显示,2021 年全网小程序数量已超 700 万,其中微信小程序开发者突破 300 万,DAU 超过 4.5 亿:日均使用次数同比增 ...

  9. java实现ssh连接工具类

    import ch.ethz.ssh2.Connection;import ch.ethz.ssh2.Session;import ch.ethz.ssh2.StreamGobbler;import ...

  10. 微信小程序循环列表点击每一个单独添加动画

    首先,咱们看一下微信小程序动画怎么实现,我首先想到的是anime.js,但是引入之后用不了,微信小程序内的css也无法做到循环的动态,我就去找官方文档看看有没有相应的方法,哎,还真有 点击这里查看 微 ...