问题现象

Oracle、Mysql数据库链接串,JDBC驱动连接串可以指定客户端的编码格式:

jdbc:mysql://hostname:port/database_name?useUnicode=true&characterEncoding=utf8mb4

jdbc:oracle:thin:@//hostname:port/service_name?NLS_LANGUAGE=AMERICAN&NLS_TERRITORY=AMERICA&NLS_CHARACTERSET=UTF8

YashanDB JDBC连接串没有对应的参数:连接数据库 | YashanDB Doc

经常收到客户的反馈,YashanDB JDBC没有对应的字符编码参数设置,客户端和服务端编码不一致,要怎么处理?同样的OCI接口是否有对应的字符编码参数可以设置?

问题的风险及影响

YashanDB已解决,无风险。

问题影响的版本

YashanDB JDBC/OCI驱动所有版本

问题发生原因

使用问题,详见问题分析和处理过程。

解决方法及规避方式

非问题,无须规避

问题分析和处理过程

了解字符编码

通常我们会遇到UTF-8、GBK,为了解背后的机制,还需要了解字符集、编码的一些知识:

  • 字符集:抽象二进制和字符间的对应关系,这套对应关系不考虑具体实现,只确定映射本身。GBK就是一套字符集。

  • 编码:计算机二进制和字符间的对应关系的实际编码实现,这套映射体现在计算机实际存储字符串的二进制序列上。UTF-8就是一种编码的方式。

  • ASCII 码:一共规定了128个字符的编码,最前面的一位统一规定为0

  • Unicode:国际标准字符集,现在的规模可以容纳100多万个符号。每个符号的编码都不一样。

  • UTF-8:Unicode Transformation Format,互联网上使用最广的Unicode的一种实现,对英文使用8位(即一个字节),中文使用24位(三个字节)来编码,另外还有UTF-16、Oracle常见的AL32UTF8等

  • GBK: 严格来说是汉字字符集定义,也可以看做字符编码方式,因为它定义汉字字符集的同时也规定了如何将这些字符编码转换为二进制字节序列。有下面多种,GB2312使用2个字节来编码。

GBK、GB2312等与UTF8之间通过Unicode编码能相互转换:

  • GBK、GB2312 --先转--> Unicode --再转--> UTF8

  • UTF8 --先转--> Unicode --再转--> GBK、GB2312

相应的资料比较多,可以参考这篇:字符编码那点事:快速理解ASCII、Unicode、GBK和UTF-8 - 知乎 (zhihu.com)

YashanDB JDBC自动转码

JAVA的StringCoding提供了字符转换工具,YashanDB JDBC驱动利用了该工具实现了自动编解码:

首先驱动会读取JVM的编码设置,假如服务端字符集与JVM字符集不同,则:

  • 把数据从客户端传到服务端时,JDBC自动按照服务端设置的字符集进行转换。

  • 从服务端传数据到客户端时,JDBC按照客户端设置的字符集进行编码。

/**
* Encodes this {@code String} into a sequence of bytes using the given
* {@linkplain java.nio.charset.Charset charset}, storing the result into a
* new byte array.
*
* <p> This method always replaces malformed-input and unmappable-character
* sequences with this charset's default replacement byte array. The
* {@link java.nio.charset.CharsetEncoder} class should be used when more
* control over the encoding process is required.
*
* @param charset
* The {@linkplain java.nio.charset.Charset} to be used to encode
* the {@code String}
*
* @return The resultant byte array
*
* @since 1.6
*/
public byte[] getBytes(Charset charset) {
if (charset == null) throw new NullPointerException();
return StringCoding.encode(charset, value, 0, value.length);
}

所以无论在什么情况下都不会出现乱码问题,用户不需要去关心JDBC字符集,也不需要设置字符集。

YashanDB OCI指定客户端编码

OCI需要指定客户端的字符集,相关的语句:

errcode = OCIEnvNlsCreate((OCIEnv**)&envhpSessionRelease, (ub4)OCI_THREADED, (dvoid*)0,
(dvoid * (*)(dvoid*, size_t))0, (dvoid * (*)(dvoid*, dvoid*, size_t))0,
(void (*)(dvoid*, dvoid*))0, (size_t)0, (dvoid**)0, 852, 0);

目前崖山只支持852和871:

#define YCI_UTF8ID 871
#define YCI_ZHS16GBK 852

例如要指定编码格式为GBK,就把852通过该接口传进去,崖山的OCI接口就可以通过852来识别出是要支持 ZHS16GBK,具体支持的值对应的字符集参考:oracle Nls_Charset_Id 字符集编码表_1507对应的字符集编码-CSDN博客

经验总结

1、JDBC不需要指定编码格式,会自动编解码。

2、OCI需要通过接口OCIEnvNlsCreate指定编码格式,目前只支持2种编码。

【YashanDB知识库】YashanDB的JDBC/OCI驱动如何设置字符编码的更多相关文章

  1. Oracle JDBC:驱动版本区别与区分 [转]

    classes12.jar,ojdbc14.jar,ojdbc5.jar和ojdbc6.jar的区别,之间的差异 在使用Oracle JDBC驱动时,有些问题你是不是通过替换不同版本的Oracle  ...

  2. JDBC 常用驱动类及url格式

    1. oracle <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</ ...

  3. JDBC注册驱动的三种方式

    JDBC注册驱动的三种方式 1.通过导入的JDBC的驱动包拿到的com.mysql.jdbc.Driver对象,利用java.sql.DriverManager对象的DriverManager.reg ...

  4. Qt编译Oracle OCI驱动

    最近使用qt开发了一个访问数据库的工具, 默认使用ODBC驱动注入的方式,后来发现Oracle中ODBC驱动注入经常失败. 后来就想直接使用OCI方式访问,而默认情况下Qt只有Sqlite和ODBC驱 ...

  5. Qt5.5.1和Qt5.3.2编译OCI驱动教程及验证方法

    我们都知道oracle数据库的强大,并且好多企业或者教学用到数据库时都会推荐使用.但是Qt因为版权问题没有封装oracle数据库专用驱动,网上也有一大堆说法和教程,但是或多或少的都有问题.下面废话不多 ...

  6. Java笔记4:JDBC纯驱动方式连接Oracle

    JDBC纯驱动方式连接Oracle 1 下载Oracle提供的驱动程序包 下载地址: http://www.oracle.com/technetwork/database/enterprise-edi ...

  7. [转]JDBC如何进行超时设置

    文档来源:https://jingyan.baidu.com/article/fc07f98922615a12ffe519ce.html 恰当的JDBC超时设置能够有效地减少服务失效的时间.本文将对数 ...

  8. JDBC超时原理与设置

    抄录自网上,因为担心以后找不到,因此抄录之.感谢分享的大神! 英文原版:http://www.cubrid.org/blog/dev-platform/understanding-jdbc-inter ...

  9. jmeter—JDBC request动态参数设置

    jmeter—JDBC request动态参数设置 重要参数说明: Variable Name:数据库连接池的名字,需要与JDBC Connection Configuration的Variable ...

  10. LCD驱动分析(一)字符设备驱动框架分析

    参考:S3C2440 LCD驱动(FrameBuffer)实例开发<一>   S3C2440 LCD驱动(FrameBuffer)实例开发<二> LCD驱动也是字符设备驱动,也 ...

随机推荐

  1. P6626 题解

    有一个很暴力的解法,就是以询问点为根 DFS. 考虑优化,我们考虑优化换根. 当根节点从父亲移动到它的某个孩子时,孩子的子树内所有点深度减 \(1\) 其余点深度加 \(1\). 同理,当根节点从某个 ...

  2. 在linux系统中,对标准输出(stdout,文件描述符为 1)和标准错误(stderr,文件描述符为 2)重定向到文件

    请参考:2>/dev/null和>/dev/null 2>&1和2>&1>/dev/null的区别 下面的是本人浅尝辄止了,并非全貌,还是上面的文章说的比 ...

  3. Spring5.X常见的注入方式

    使用set方法注入 Video.java package net.cybclass.sp.domain; public class Video { private int id; private St ...

  4. 解决方案 | Chrome/Edge 总是自动修改我的pdf默认打开方式

    1.问题描述 最近我的pdf文件总是被chrome打开(如图1),而且点击属性,更改别的pdf阅读器也不管用(如图2),此时的chrome就像个流氓软件一样. 图1 被chrome劫持 图2 点击属性 ...

  5. AI驱动音乐创新,网易数帆X云音乐刷新MIREX世界纪录 网易数帆 网易数帆

    在近期揭榜的2021国际音频检索评测大赛(MIREX)上,网易数帆易智语音团队携手网易云音乐音视频实验室,凭借生产级AI技术创新能力,在歌词识别和歌单识别两个赛道大幅打破世界纪录夺得冠军. MIREX ...

  6. [oeasy]python005_退出游乐场_重启游乐场_系统态shell_应用态_quit

    退出终端_重启游乐场_shell_quit Python 回忆 上次 了解了 python 进入了 python 游乐场   在游乐场 可以做 简单的计算 还可以做 乘方运算   数字特别大之后 游乐 ...

  7. 数据仓库建模工具之一——Hive学习第四天

    Hive的基本操作 1.3HIve的表操作(接着昨天的继续学习) 1.3.2 显示表 show tables; show tables like 'u*'; desc t_person; desc f ...

  8. centos7 扩展硬盘

    新增硬盘后 fdisk -l fdisk /dev/sdb (以后再加改成c) 阿里云叫vdb fdisk -l 注意,最好跟第一块硬盘一样! df -T 查看硬盘分区格式 注意,文件夹不能已存在的! ...

  9. douyin 今日头条 巨量登录滑块和douyin详情滑块分析

    声明(lianxi a15018601872) 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容.敏感网址.数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均 ...

  10. 普通用户权限运行docker

    docker安装后默认权限是管理员,在Ubuntu系统中需要使用sudo命令,但是很多时候docker的拉取操作都是写在脚步里面的,因此执行的时候十分的难搞,如果给脚本sudo权限后那么整个的环境路径 ...