环境:
DB-A字符集:US7ASCII
DB-B字符集:ZHS16GBK
需求:从DB-A中将一个表的中文数据通过JAVA定时任务同步到DB-B.
DB-A库中表的信息如下:
CREATETABLEUSER_INFO(USER_IDnumber,USER_NAMEvarchar2(50));
如果用一般的方式来SELECT,和INSERT,不管客户端用什么样的字符集,数据到DB-B上肯定会显示乱码。
解决方法1(在数据库实现)
解决思路:通过视图将数据转换成二进制数据,绕过字符集的转换,然后让目标库来读取。
1.在DB-A库上创建视图:
createorreplaceviewview_user_info as selectuser_id,utl_raw.cast_to_raw(user_name)user_namefromuser_info; |
2.在DB-B库上创建视图:
createorreplaceviewview_user_info_db_a as selectuser_id,utl_raw.cast_to_varchar2(user_name)user_namefromview_user_info@db_a; |
3.在DB-B库上进行数据读取:
selectuser_id,user_namefromview_user_info_db_a; |
这时显示出来的数据才是正确的!
其实就是:selectutl_raw.cast_to_raw(‘中华人民’),utl_raw.cast_to_varchar2(‘D6D0BBAAC8CBC3F1’)fromdual;
优点:对JAVA程序来说是透明的,无所改动代码。
数据提取时,与客户端字符集无关
缺点:增加数据库CPU开销
–Examda提示学习到方法:
解决方法2(在JAVA实现)
使用JAVA的两个函数来实现:getBytes(),newString()
先来看一下这两个函数:
.getBytes(charset)
这是java字符串处理的一个标准函数,其作用是将字符串所表示的字符按照charset编码,并以字节方式表示。
注意字符串在java内存中总是按unicode编码存储的。
比如“中文”,正常情况下(即没有错误的时候)存储为“4e2d6587”,
如果charset为“gbk”,则被编码为“d6d0cec4”,然后返回字节“d6d0cec4”。
如果charset为“utf8”则最后是“e4b8ade69687”。
如果是“iso8859-1”,则由于无法编码,最后返回“3f3f”(两个问号)。
.newString(charset)
这是java字符串处理的另一个标准函数,和上一个函数的作用相反,将字节数组按照charset编码进行组合识别,最后转换为unicode存储。
参考上述getBytes的例子,“gbk”和“utf8”都可以得出正确的结果“4e2d6587”,但iso8859-1最后变成了“003f003f”(两个问号)。
因为utf8可以用来表示/编码所有字符,所以newString(str.getBytes(“utf8”),“utf8”)===str,即完全可逆。
对于以上两个函数,我们可以有两种用法来解决这个问题:
方法2.1
a)无需关心客户端NLS_LANG的设置
b)从数据库取出字符的二进制编码:
selectuser_id,utl_raw.cast_to_raw(user_name)user_namefromuser_info;
c)在java用其所newString(username,‘GBK’)转成中文
d)插入到目标库
方法2.2(推荐)
a)将JAVA客户端NLS_LANG设置为US7ASCII
b)从数据库直接取出字段值
selectuser_id,user_namefromuser_info;
(这时因为客户端和服务器的字符集一致,所以会得到正确的中文显示)
c)将中文进行转码为GBK:
newString(user_name.getBytes(“gbk”),“gbk”)
d)得到正确的GBK中文编码插入到目标库
优点:代码完全由JAVA控制,无需作数据库变更,数据库的压力转移到了JAVA客户端。
注意:必须把客户端的字符集和服务器端的字符集设置成一样
我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。
我原创,你原创,我们的内容世界才会更加精彩!
【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】
微信公众号
TechTarget
官方微博
TechTarget中国
相关推荐
-
怎么可以让两个服务器实现数据同步?
-
内存数据网格提供商一头扎进Java
10年的时间里,应用性能解决方案提供商Alachisoft一直在用NCache(针对N-Tier和网格计算.NET应用的内存计算和数据网格产品)为.NET社区服务。
-
遇到这样一个问题:通过java service wrapper部署应用,wrapper进程占用的内存会一直升高, 直到把内存吃完应用崩溃,但是这个wrapper
遇到这样一个问题:通过java service wrapper部署应用,wrapper进程占用的内存会一直升高 […]
-
Google App Engine for Java 对于目前中国需要学习吗?