Oracle JDBC连接URL必须显式指定characterEncoding参数以避免中文乱码,因驱动不自动读取数据库NLS_CHARACTERSET;需根据数据库实际字符集(如AL32UTF8或ZHS16GBK)设置,并与useUnicode=true配合使用,且参数须置于spring.datasource.url内、用&连接。
Oracle JDBC连接URL里必须显式指定characterEncoding
java应用连oracle时出现中文乱码,90%以上是因为jdbc url没带字符集参数,驱动默认用平台编码(比如windows上是gbk),而oracle数据库实际用的是al32utf8或zhs16gbk。jdbc驱动不会自动读取数据库的nls_characterset,必须人工对齐。
正确做法是在jdbc:oracle:thin:@后面追加?characterEncoding=UTF-8(注意:这个参数对Oracle官方驱动ojdbc8.jar及以上版本有效;旧版ojdbc6不支持该参数,需换用其他方式)。
- 推荐写法:
jdbc:oracle:thin:@//host:1521/orclpdb?characterEncoding=UTF-8&useUnicode=true -
useUnicode=true要和characterEncoding=UTF-8一起用,否则可能被忽略 - 如果数据库是ZHS16GBK编码,这里就得写
characterEncoding=GBK,不能硬套UTF-8 - URL中所有参数必须用
&连接(XML/HTML转义),不是&
检查Oracle服务端字符集,别只看客户端
很多人只改Java代码或URL,却没确认Oracle实例本身的字符集是否支持中文。乱码可能是服务端存的就是乱码——比如建库时用了AMERICAN_AMERICA.US7ASCII,那再怎么设URL也没用。
登录SQL*Plus或SQL Developer,执行:
SELECT * FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER IN ('NLS_CHARACTERSET', 'NLS_NCHAR_CHARACTERSET');
- 常见合法值:
AL32UTF8(推荐)、ZHS16GBK、ZHT16BIG5 - 如果返回
US7ASCII或WE8ISO8859P1,说明数据库根本不支持中文存储,需重建库或导出重建 -
NLS_NCHAR_CHARACTERSET控制NVARCHAR2/NCHAR类型,一般设为AL16UTF16即可,不影响普通VARCHAR2
PreparedStatement设参数前不用手动编码转换
有人习惯在执行preparedStatement.setString(1, new String(str.getBytes("ISO-8859-1"), "UTF-8"))这类操作来“修复”乱码,这是典型误区。Oracle JDBC驱动在setString()时会自动按连接指定的字符集编码,手动转码反而造成二次编码,让乱码更严重。
立即学习“Java免费学习笔记(深入)”;
- 只要URL里
characterEncoding设置正确,且数据库字段是VARCHAR2(非RAW等二进制类型),直接ps.setString(1, "中文")即可 - 确保Java源文件本身保存为UTF-8(IDE里检查文件编码,不是项目编码)
- Maven编译时加上
<encoding>UTF-8</encoding>,避免javac用系统默认编码读源码
Spring Boot + MyBatis环境下容易漏掉的配置点
用spring.datasource.url配置时,很多人把characterEncoding参数写在application.yml的末尾,结果被YAML解析器当成了嵌套结构或注释掉;或者误加在spring.datasource.hikari下面,而HikariCP不识别该参数,它只透传给底层JDBC驱动。
- 必须写在
spring.datasource.url字符串内部,例如:spring: datasource: url: jdbc:oracle:thin:@//localhost:1521/orclpdb?characterEncoding=UTF-8&useUnicode=true - HikariCP或Druid等连接池不会修改JDBC URL语义,但会过滤未知参数——所以错放位置等于没设
- 如果用了MyBatis的
configuration.variables,别把characterEncoding当成MyBatis变量去替换,它属于JDBC层
Oracle字符集问题从来不是单点问题:URL参数、服务端配置、Java源码编码、构建工具链,四个环节只要一个没对齐,中文就可能变问号或方块。最常被跳过的其实是查NLS_DATABASE_PARAMETERS这一步——很多人连数据库到底用什么字符集都不知道,就在代码里反复试参数。


















