异常信息

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. Go 里面的 ^ 和 &^

    这几天在研究 Go 的源码,突然发现了一个之前没有见过的位运算,见这里 new &^= mutexWoken & 和 ^,分别表示 AND 和 XOR,这个不用多说. 值得一提的是 ^ ...

  2. python-杨辉三角形

    [题目描述]输出n(0<n)行杨辉三角形,n由用户输入. [练习要求]请给出源代码程序和运行测试结果,源代码程序要求添加必要的注释. [输入格式]一行中输入1个整数n. [输出格式]输出n行杨辉 ...

  3. 【Android开发】EasyPermissions 请求权限

    安卓6.0以后,开发应用的时候,仅在AndroidManifest.xml中申请权限已经不可以了,需要在代码中动态申请. 现在看一个google推出的机制:EasyPermissions 引入步骤: ...

  4. myEclipse开发内存溢出解决办法myEclipse调整jvm内存大小 java.lang.OutOfMemoryError: PermGen space及其解决方法

    Window->Preferences->MyEclipse->Servers->Tomcat x.x->JDK->Optional Java VM argumen ...

  5. node的两种随起随用静态服务器搭建

      一. anywhere Anywhere是一个随启随用的静态服务器,它可以随时随地将你的当前目录变成一个静态文件服务器的根目录. 1.确定电脑上安装了node.js 2.在当前所在项目文件夹下输入 ...

  6. 【转载】【zabbix】自定义监控项key值

    [转载]https://www.cnblogs.com/zhenglisai/p/6547402.html [zabbix]自定义监控项key值   说明: zabbix自带的默认模版里包括了很多监控 ...

  7. 基于PromiseA+规范实现一个promise

    实现如果下规范的promise Aplus规范 1,promise是一个类:有三个状态 pending/等待态 fulfilled/成功态 rejected/失败态 2,promise默认执行器立即执 ...

  8. 控制反转 IOC 理论推导

    控制反转 IOC 理论推导 按照我们传统的开发,我们会先去 dao 层创建一个接口,在接口中定义方法. public interface UserDao { void getUser(); } 然后再 ...

  9. int bool str

    一. python的基本数据类型 1. int 整数 2. bool 布尔.  判断.  if  while 3. str  字符串 ,一般存放小量的数据 4. list  列表. 可以存放大量的数据 ...

  10. Spring配置文件-Bean实例化的三种方式

    1.无参构造方法实例化(详见我的博客) 2.工厂静态方法实例化 创建StaticFactory类 public class StaticFactory { public static UserDao ...