问题现象

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. Java开发框架演变过程

    JavaWeb开发简史 Java框架创始人 Java框架说明 Spring: 把应用程序中的bean统一交给Spring进行管理控制,简化了我们的代码操作,和降低了代码的耦合度,Spring框架基本上 ...

  2. Java-JSP既可以指定定义HTML标签,又可以定义java代码

    概念: Java Server Pages:java服务器端页面 可以理解为:一个特殊页面,其中既可以指定定义HTML标签,又可以定义java代码 用于简化书写 原理: JSP本质上就是一个Servl ...

  3. Bootstrip HTML 查询搜索常用格式模版

    Bootstrip HTML 查询搜索常用格式模版 <form class="form-inline my-3 d-flex align-items-center justify-co ...

  4. Java21的虚拟线程Virtual Thread初体验

    我们之前使用的是操作系统平台的线程,就称之为"系统线程"吧.虚拟线程是JDK维护的,原理跟WebFlux的底层实现差不多,都是工作线程分离. 要使用虚拟线程,需要使用JDK21以上 ...

  5. [oeasy]python0018_ ASCII_字符分布_数字_大小写字母_符号_黑暗森林

    ​ 打包和解包 回忆上次内容 decode 就是解码 解码和编码可以转化 encode 编码 decode 解码 互为逆过程 大小写字母之间序号全都相差(​​32​​)​​10进制​​ ​ 编辑 这是 ...

  6. AT_arc111_a 题解

    洛谷连接&Atcoder 链接 题目简述 给定两个数 \(n\) 和 \(m\),输出 \(\left\lfloor\frac{10^n}{m}\right\rfloor \bmod m\) ...

  7. Android SDK Build-tools的版本已经高于Android SDK Platform-tools版本 的解决办法

    解决Unknown error: Unable to build: the file dx.jar was not loaded from the SDK folder!最近渐渐迁移到Android  ...

  8. ABC348

    A link 这道题就先输出整个的\(oox\),再输出剩一个两个的. 点击查看代码 #include<bits/stdc++.h> using namespace std; int n; ...

  9. LOTO示波器功率分析功能

    LOTO示波器软件在非标功能中增加了功率分析功能,对当前屏幕的电压波形和电流波形进行了瞬时功率,视在功率以及有功功率/平均功率的分析计算. 有功功率是指电器所消耗的电能,用于产生热能.机械能或光能等, ...

  10. windows中新建文件菜单消失的解决办法

    具体解决办法: https://jingyan.baidu.com/article/cbcede07577f4702f40b4dfd.html 右键中新建文本文件 菜单消失: 注册表编辑器: 路径: ...