问题现象

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. Spring(XML方式)简单入门

    环境准备 maven jdk Spring Eclipse 项目创建 pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0 ...

  2. [rCore学习笔记 013]GDB跟踪程序

    题目要求 请学习 gdb 调试工具的使用(这对后续调试很重要),并通过 gdb 简单跟踪从机器加电到跳转到 0x80200000 的简单过程.只需要描述重要的跳转即可,只需要描述在 qemu 上的情况 ...

  3. 数据类型的别名&&随机数_C

    // Code file created by C Code Develop #include "ccd.h" #include "stdio.h" #incl ...

  4. 手把手教你本地运行Meta最新大模型:Llama3.1,可是它说自己是ChatGPT?

    就在昨晚,Meta发布了可以与OpenAI掰手腕的最新开源大模型:Llama 3.1. 该模型共有三个版本: 8B 70B 405B 对于这次发布,Meta已经在超过150个涵盖广泛语言范围的基准数据 ...

  5. 安卓网络通信之 ​HttpURLConnection​ 文件上传

    文件上传分为二步,第一步选择文件 代码思路是: chooseFile()​方法用于创建一个Intent对象,并设置Intent的Action为ACTION_GET_CONTENT,这表示获取内容,即选 ...

  6. scratch源码下载 | 飞天厨师

    程序说明: <飞天厨师>是一款使用Scratch平台制作的游戏程序.在这个游戏中,玩家将控制一名厨师角色,他在天空中不断掉落.玩家需要利用方向键左右移动厨师,以便他能够准确地踩在空中的食物 ...

  7. jmeter测试udp广播(jmeter发送udp)

    jmeter测试udp广播(jmeter发送udp) jmeter测试udp广播(jmeter接收udp) 先下载安装第三方插件 下载链接:https://jmeter-plugins.org/ins ...

  8. 大厂面经: 字节跳动 iOS开发实习生-飞书

    好家伙, 线上面试,总时长1h30mins左右 整体流程: 0.自我介绍(0-2mins) 1.做的比较难的事情(15min) 我讲我之前写的一个低开平台,写了一个撤销回退功能,提了个pr,用了节流, ...

  9. 【ELK】Kibana-7.13.1版本 启动报错 Centos6

    报错信息: [root@centos6-1 gcc-4.8.2]# /opt/kibana-7.13.1-linux-x86_64/bin/kibana /opt/kibana-7.13.1-linu ...

  10. 【Web】实现页面自动刷新的功能

    技术发现自: https://www.bilibili.com/video/BV14v411b7JS?p=8 摘要自CSDN帖子: https://blog.csdn.net/senbar/artic ...