测试配置
用户实例配置,my.cnf [mysqld] default-character-set = gbk
测试结论
characterEncodingAsString 为JDBC中的字符编码
serverCharsetIndex 为jdbc中存储的server端编码
serverCharSet (我们用这个变量来代表实际mysql server会话连接编码)
当调用setNames的时候jdbc的上面两个值都没有更新,但是mysql server端是更新了,所以出现了乱码。
without characterEncoding=UTF-8 | with characterEncoding=UTF-8 | |
doHandshake阶段 |
characterEncodingAsString = null serverCharsetIndex = 28 (GBK) serverCharSet = gbk
socket交互统一使用characterEncodingAsString 如果为null,则使用UTF-8
|
characterEncodingAsString = utf8 serverCharsetIndex = 28 (GBK) serverCharSet = utf8
jdbc同socket交互统一使用characterEncodingAsString 也就是UTF-8,其实这里我猜测发送了个set name utf8命令过去了,具体代码得看下mysql的源码了。
|
configureClientCharacterSet阶段 |
characterEncodingAsString = GBK serverCharsetIndex = GBK serverCharSet = gbk
|
characterEncodingAsString = utf8 serverCharsetIndex = 28 (GBK) serverCharSet = utf8
|
执行SQL阶段 | 此时执行SQL都是使用GBK编码所以不会乱码 |
其实本以为这里会乱码的,后来想明白了,原来serverCharsetIndex = 28这个值在jdbc里面已经是错误的了,不用关注。虽然JDBC内部两个变量不一致,但 是characterEncodingAsString 和mysql server端的编码方式是一致的。 |
set names utf8 |
characterEncodingAsString = GBK serverCharsetIndex = gbk serverCharSet = utf8 此时的jdbc端是错误的 但是此时的server的连接已经切换成utf8
|
同样不会乱码 |
set names gbk |
jdbc characterEncodingAsString = utf8 serverCharsetIndex = 28 (GBK) serverCharSet = gbk
|
|
执行SQL阶段 |
此时JDBC将SQL转为GBK,而同时服务端使用的是UTF8编码 所以出现乱码问题 |
执行失败,中文乱码了。 因为characterEncodingAsString 和serverCharSet 不一致。 |
JDBC URL不带characterEncoding=UTF-8的测试场景
1. doHandshake前阶段
从ConnectionImpl.java定位到ConnectionImpl()函数里面的
initializeDriverProperties(info); -->
postInitialization(); -->
this.characterEncodingAsString = ((String) this.characterEncoding.getValueAsObject());
从这里可以看出characterEncodingAsString这个变量取值是null
2. doHandshake阶段
从ConnectionImpl.java定位到ConnectionImpl()函数里面的 -->
createNewIO(false);-->
connectOneTryOnly(isForReconnect, mergedProps); -->
coreConnect(mergedProps); -->
this.io.doHandshake(this.user, this.password, this.database);-->
this.serverCharsetIndex = buf.readByte() & 0xff;
这里可以看出mysql server socket 用一个int表示编码类型,
具体mysql server从根据哪个参数的编码类型来发这个int 需要查看mysql源码,猜测是default-character-set
其实里面有个map根据这个int 就可以获取到相应的编码类型
this.io.doHandshake(this.user, this.password, this.database);-->
secureAuth411(null, packLength, user, password, database, true); -->
String enc = getEncodingForHandshake(); -->
packet.writeString(user, enc, this.connection); -->
writeStringNoNull(s, encoding, encoding, false, conn);
3.configureClientCharacterSet阶段
connectOneTryOnly(isForReconnect, mergedProps); -->
initializePropsFromServer(); -->
configureClientCharacterSet(false); -->
获取第二步编码类型
realJavaEncoding = getEncoding(); // 获取url的编码 这里是null
String serverEncodingToSet = CharsetMapping.getJavaEncodingForCollationIndex(this.io.serverCharsetIndex);
setEncoding(serverEncodingToSet);
这里差不多完成了编码的赋值,执行executeSQL的时候就会调用这两种编码。
JDBC URL带characterEncoding=UTF-8
-
doHandshake前阶段
代码同上可以看到characterEncodingAsString 已经能够取到utf8,所以使用socket验证的时候都会使用utf8编码进行。
this.characterEncodingAsString = ((String) this.characterEncoding.getValueAsObject());
这个props参数中包含了characterEncoding=UTF-8属性,所以猜测mysql server接受到的报文中含有这个参数,会自动
调用set names utf8。因为JDBC源码中发现没有在这里设置set names但是连接的character_set_client,character_set_connection
的两个变量都从gbk变成了utf8。
character_set_client
2. doHandshake阶段
和上面类似。
3.configureClientCharacterSet阶段
realJavaEncoding = getEncoding(); // 获取url的编码 这里是null
String serverEncodingToSet = CharsetMapping.getJavaEncodingForCollationIndex(this.io.serverCharsetIndex);
setEncoding(serverEncodingToSet);
代码已经将characterEncodingAsString 设置成GBK因为mysql server是GBK的
这块比较特殊,发现代码的后面还会将characterEncodingAsString设置成UTF-8,
所以在jdbc中debug的时候这两个编码不一样,却不出现乱码,因为jdbc的编码语言和服务端是一致的。
相关推荐
* mysql:使用mysql的jdbc服务 * localhost:使用本地的mysql的jdbc服务 * 3306:使用本地的3306端口的mysql的jdbc服务 * ------- * jt_db 使用的数据库 * characterEncoding=utf-8 设置编码...
目标 一、主从表数据更新问题 当两张表没有建立任何关系的时候,那么可以随意删除其中任何一张表中的任何记录,但是一旦把两张表建立了关系之后,那么不能删除主表中的...1 查看MySQL编码 2 控制台编码 3 MySQL工具
7.提供多语言支持,常见的编码如中文的GB 2312、BIG5,日文的Shift_JIS等都可以用作数据表名和数据列名。 8.提供TCP/IP、ODBC和JDBC等多种数据库连接途径。 9.提供用于管理、检查、优化数据库操作的管理工具。 10...
Java之JDBC连接数据库实现增删改查(2018 使用Dao层实现 完美封装解决硬编码问题 使用预编译对象PreparedStatement) 配置文件 db.properties(保存数据库账号和密码等) 工具类 JDBCUtil.java(抽取公共部分,解决硬...
7.提供多语言支持,常见的编码如中文的 GB 2312、BIG5,日文的 Shift_JIS等都可以用作数据表名和数据列名。 8.提供 TCP/IP、ODBC 和 JDBC等多种数据库连接途径。 9.提供用于管理、检查、优化数据库操作的管理工具...
期末数据库课程设计基于Java+MySQL+JDBC+JavaSwing的简易图书进销管理系统源码+数据库 期末数据库课程设计, 图书进销信息管理系统 直接将数据库文件导入就可以快速建表 编码: GBK 开发环境 jdk12+MySQL8.0 推荐...
2.8.4. 处理MySQL编译问题 2.8.5. MIT-pthreads注意事项 2.8.6. 在Windows下从源码安装MySQL 2.8.7. 在Windows下编译MySQL客户端 2.9. 安装后的设置和测试 2.9.1. Windows下安装后的过程 2.9.2. Unix下安装后的过程 ...
图书管理系统项目使用eclipse开发工具和MySql数据库进行开发,maven方式创建项目,编码格式为utf-8(如出现乱码可改成utf-8), 项目分成三层架构,数据访问层、业务逻辑层和表现层,并没有使用框架等复杂的技术,...
编码液修正了所有错误网址: : Git发布: : Website for a Startup company named Codingliquids. A enterprise website with Admin panel, MVC architecture and Dynamic data parsing .图片为了安全起见,未显示...
主要说明JDBC存入数据的编码问题(中文)基本包括所有的问题,亲自体验过,很好
期末数据库课程设计基于Java+MySQL+JDBC+JavaSwing的超市管理系统源码+数据库 编码: GBK 开发环境 jdk12+MySQL8.0 补充 UI美化(引用当前系统的风格) 在每个有组件的文件的构造函数中加入以下代码即可。 try { ...
为了完整起见,我们将使用可配置的属性而不是硬编码的值,以捕获Spring的本质。 欢迎学生使用任何键/值对。 推荐的样品对如下所示 可以根据您的本地实例随意编辑连接属性 范围 描述 simpleJdbc.driver com.mysql
工具类 JDBCUtil.java(抽取公共部分,解决硬编码问题 DBCP方式实现连接池、配置连接池 ==> 获得连接对象连接数据库) 用户账号实体类 User.java(私有化数据库t_user表中的id,username,password) 接口类 ...
Java之JDBC连接数据库实现增删改查(2018 使用Dao层实现 完美封装解决硬编码问题) 配置文件 db.properties(保存数据库账号和密码等) 工具类 JDBCUtil.java(抽取公共部分,解决硬编码问题) 用户账号实体类 User....
基于Javaweb的超市管理系统毕业设计项目源码 ... url=jdbc:mysql://localhost:3306?useUnicode=true&characterEncoding=utf-8 user=root password=666666 编写数据库的公共类 编写字符编码过滤器 导入静态资源
jdbc连接mysql出现了乱码,总结起来就是里面的四个编码方式是一样的时候,就不会乱码了,简之,客户连接数据库返回结果(编码必须一致)。
MySQL 存储过程中, 表和数据的编码与数据库和存储过程默认的编码不同则可能出现 sql 不会使用索引的情况, 因为 MySQL 会对条件列的数据做相应的编码转换, 比如以下, 表数据为 latin1, MySQL 解析器会做一些转换: ...
学山智慧物业管理系统采用了目前最新版的 Servlet6.0+JDBC+MySQL8 来实现,项目使用目前在企业开发中广泛采用的前后端分离架构,所有的接口都按照规范的 RESTful 来实现。 本视频会带领各位同学从需求分析开始,了解...
在整个流程中,出现错误的原因可能是三个:post未设置编码或者编码不相符合,jdbc出现问题,linux下mysql初始码制问题。 在经过繁琐的排查后,最终确定问题为mysql编码问题。下文介绍如何解决linux下mysql中文乱码...
utf-8编码可能2个字节、3个字节、4个字节的字符,但是MySQL的utf8编码只支持3字节的数据,而移动端的表情数据是4个字节的字符。如果直接往采用utf-8编码的数据库中插入表情数据,Java程序中将报SQL异常: java.sql....