解决Ubuntu上因为Oracle编码不一致导致的中文乱码有关问题

解决Ubuntu下因为Oracle编码不一致导致的中文乱码问题

作者:Willam2004

 

引言:

做程序开发经常会与数据库打交道,Ubuntu下连接Oracle数据库的工具也不少,如:SQuirreL SQL Client,SQLDeveloper等。但这些工具连接我们公司的数据库查询中文字符串时都是乱码。上网查了下(http://*.chinaunix.net/db/oracle/2001-04-16/1166.shtml),主要是因为服务器的字符集编码与本地客户端的编码不一致。执行:

    select * from V$NLS_PARAMETERS

 发现:NLS_CHARACTERSET 为"US7ASCII",说明oracle安装的字符集为ISO-8859-1,而我们访问的应用客户端形式多为GBK编码格式。但在我们的web应用中,对于中文显示却是正常的。是因为我们通过一种jdbcproxy包进行了编码转换,如配置:

			
<bean id="unpooledDataSource" class="com.mchange.v2.c3p0.DriverManagerDataSource">
<property name="driverClass">
				<value>com.alibaba.china.jdbc.SimpleDriver</value>
			</property>
	
			<property name="jdbcUrl">
				<value>jdbc:oracle:thin:@xx.xx.xx.xx:1521:xx</value>
			</property>
			<property name="properties">
				<props>
					<prop key="user">xxx</prop>
					<prop key="password">xxx</prop>
					<prop key="bigStringTryClob">true</prop>
					<prop key="clientEncoding">GBK</prop>
					<prop key="serverEncoding">ISO-8859-1</prop>
				</props>
			</property>
		</bean>
 

 

 

从配置可以看到,SimpleDriver是实现Driver接口的实现类,但真正的驱动程序的注册还是依赖Oracle的驱动程序的实现。其中最关键的配置参数:clientEncoding,serverEncoding,前者是指定客户端的字符集编码,serverEncoding是指定服务器端字符集编码。clientEncoding需要与本地的字符集要一致,serverEncoding与oracle的字符集要一致。

 

解决方案:

 

在SQuirreL SQL Client 可以指定数据库驱动程序,将jdbcproxy和oracle dirver的jar包添加进去(jdbcproxy依赖oracle driver包),但添加后,查询中文字符仍然乱码。

 

不行是因为应用通过spring注入方式将clientEncoding和serverEncoding进行了注入,在SQuirrel SQL Client没有进行指定。接下来很简单了,做一个jdbc-proxy的patch包,增加如果默认没有指定clientEncoding和serverEncoding,那么设定clientEncoding=GBK,serverEncoding=ISO-8859-1。

 

重新加入jdbcproxy,中文字符正常显示!

 原理:

 

jdbcproxy最关键的地方,是通过代理模式,对jdbc中的各个接口,如Connection,ResultSet,Statement等,增加了CharsetParam和CharsetConvert进行字符编码的转换,而字符编码转换的核心却是非常简单的:

编码:

 

String newString = new String(oldstring.getBytes(clientEncoding),serverEncoding)

 

解码:

 

String newString = new String(oldstring.getBytes(serverEncoding),clientEncoding)

 

附类图:(工厂模式和代理模式)

解决Ubuntu上因为Oracle编码不一致导致的中文乱码有关问题


解决Ubuntu上因为Oracle编码不一致导致的中文乱码有关问题