REF CURSOR结果集乱码本质是会话字符集未对齐,Oracle完全复用当前会话NLS_CHARACTERSET解码,JDBC驱动不识别characterEncoding参数,必须用charset=AL32UTF8配置、升级ojdbc8+驱动、JVM加-Dfile.encoding=UTF-8,并通过DUMP验证底层字节。

REF CURSOR结果集乱码本质是会话字符集未对齐
不是游标本身有问题,而是JDBC驱动从Oracle读取SYS_REFCURSOR返回的ResultSet时,按错误的字符集解码了字节流。Oracle不把游标内容单独编码,它完全复用当前会话的NLS_CHARACTERSET——如果会话字符集是ZHS16GBK,但JVM用UTF-8去解,中文就变???。
必须用charset连接属性,别信characterEncoding
Oracle官方JDBC驱动(ojdbc8.jar及以上)**根本不识别**characterEncoding=UTF-8这种MySQL风格参数,加了也白加,还可能触发WARN日志干扰排查。
-
spring.datasource.hikari.data-source-properties.charset=AL32UTF8是唯一可靠写法(Spring Boot场景) - 纯JDBC需用
Properties传:props.put("charset", "AL32UTF8"),再传给DriverManager.getConnection(url, props) - URL里出现
?useUnicode=true&characterEncoding=UTF-8属于典型配置错误,删掉
驱动版本和JVM编码必须同步兜底
即使charset设对了,旧驱动或错JVM编码仍会让getResultSet()返回的字符串在Java层二次乱码。
- 强制升级到
com.oracle.database.jdbc:ojdbc8(Oracle 12c+)或ojdbc11(21c+),禁用ojdbc6及更老版本 - JVM启动参数必须带:
-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 - 若用HikariCP,建议加
connection-init-sql=ALTER SESSION SET NLS_LANGUAGE='AMERICAN' NLS_TERRITORY='AMERICA',避免NLS_LANG环境变量污染
验证不能只看getString()输出
“看起来是中文”不等于真正确——比如AL32UTF8存的字节被ISO-8859-1解,可能凑巧映射出可显字符(如ä¸Â文),但这已是损坏数据。
- 查数据库真实字符集:
SELECT value FROM nls_database_parameters WHERE parameter = 'NLS_CHARACTERSET',确认是AL32UTF8或ZHS16GBK - 查当前会话字符集:
SELECT value FROM nls_session_parameters WHERE parameter = 'NLS_CHARACTERSET',应与charset值一致 - 用
DUMP()函数验证底层字节:SELECT DUMP(name, 16) FROM user WHERE id = 1,对比返回的十六进制字节是否符合UTF-8编码规则(如中文应为C0-BF开头的三字节序列)
真正卡住人的地方,往往不是不会写registerOutParameter(1, OracleTypes.CURSOR),而是连游标都还没打开,字节流就已经在会话层被转错了。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











