Oracle数据库字符集为WE8ISO8859P1存储中文和Java读写展示

前言

之前《Oracle数据库字符集为WE8ISO8859P1存储中文和客户端程序展示中文问题》记录了类似的问题。我们发现只要客户端和服务端字符集一致,比如NLS_LANG=american_america.WE8ISO8859P1,客户端程序也能够正常用Oracle读写中文(Toad乱码属于自身问题)。

再次出现的现象

但是用Java SE客户端程序(和C++或Delphi客户端程序在同一台计算机上)访问该Oracle英文字符集数据库。发现取到的中文字符还是乱码 —— 是的,可执行程序通过设置一致的字符集解决了问题,对Java程序不管用。

分析

通过查阅资料,发现JDBC不再使用客户端的NLS_LANG这个环境变量。
而是使用了客户端系统的语言进行数据库连接???

失败尝试1

jdbc thin vs jdbc oci
无论设置无需Oracle客户端的thin模式,还是需要客户端的oci模式,都无法解决这个问题。
网上很多文章比如这篇,写的是 把 thin 改为 oci 后,就用客户端了,就可以读取NLS_LANG环境变量了, 实际测试在Oracle11g下是不行的,依然乱码。

失败尝试2

MySQL的方式并不适合Oracle数据库,后面不能带参数。

conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=utf8",

失败尝试3

看到JavaEE项目的同事这么写的:
后端在spring的配置文件配置数据据源时添加如下property

    <property name="ConnectionProperties">
    	<!-- 链接参数配置 “clientEncoding”和“serverEncoding”,分别指定数据库客户端和服务器端的字符编码 Encoding Filter从这两个参数获取编码 -->
    	<value>clientEncoding=GBK;serverEncoding=ISO-8859-1;</value>
    </property>

配置数据库连接字符串如下:

jdbc:wrap-jdbc:filters=encoding:jdbc:oracle:thin:@IP地址:1521/orcl

但是JavaSE项目并没有spring或其它框架……
同时JDBC表示并不认识wrap-jdbc是什么。

解决

方案1:每句都自己转码(麻烦死了)。

new String(result.getString(col).getBytes("ISO8859-1"), "GBK") //读数据集
new String(aValue.getBytes("GBK"), "ISO8859-1")	//写入数据库

方案2:使用阿里巴巴的Druid

官方定义:Druid是Java的数据库连接池,能够提供强大的监控和扩展功能。
阿里巴巴的《Druid简介》。请注意阿里巴巴不是阿帕奇。。。

即使去掉违反广告法的文字描述后,依然能感觉到很厉害!毕竟人形德鲁伊能变熊/豹/猎豹/水下/飞行/鸟,并且喜欢荷兰队的年纪稍大一点的朋友也都知道,范尼是德鲁伊呀。

pom.xml

<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
	<groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.22</version>
</dependency>

java

//驱动
//public static String driverClass = "oracle.jdbc.driver.OracleDriver";
public static String driverClass = "com.alibaba.druid.proxy.DruidDriver";
...
//连接字符串:
//String connurl = "jdbc:oracle:thin:@192.168.168.115:1521/testdb";
String connurl = "jdbc:wrap-jdbc:filters=encoding:jdbc:oracle:thin:@192.168.168.115:1521/testdb";
...
//设置属性(包括用户名密码):
//毕竟咱没有Spring框架可以设置编码格式。
Properties info = new Properties();
info.setProperty("user","test");
info.setProperty("password","******");
info.setProperty("serverEncoding","ISO-8859-1"); //服务端编码
info.setProperty("clientEncoding","GBK"); //客户端编码
conn = DriverManager.getConnection(connurl,info);
...

之后用正常的语句取数据,insert时也不用转码(绑定变量或直接拼字符串)。
是改老项目最方便的方法。

结论

客户端和服务器都为单字节字符集,操作系统支持中文显示。
应用程序是可以显示中文的。
但是Java SE程序只用标准JDBC是没有简单办法的。

如果您知道用标准JDBC的解决办法,请一定留言赐教啊!!!

Guess you like

Origin blog.csdn.net/ddrfan/article/details/106541702