为什么OJDBC 7不将CHAR数据类型映射到Java String?

Dol*_*ava 5 java oracle11g ojdbc

OJDBC的工作之一是将Oracle数据类型映射到Java类型.

但是,我们注意到,如果我们提供CHAR数据类型,则不会映射到java.lang.String.显示此行为的版本是:OJDBC7 v12.1.0.2OJDBC6 v12.1.0.1.旧版本确实将CHAR数据类型映射到:java.lang.String.

在深入挖掘时,我们发现有一个类:StructMetaDataoracle.jdbc.driverOJDBC 的包中实现Oracle数据类型到Java类型映射.其中有一个方法:'getColumnClassName(int arg0)'值得关注.我们注意到,对于OJDBC v7,映射到的案例java.lang.String如下:

    int arg1 = this.getColumnType(arg0);
    switch (arg1) {
    case -104:
        return "oracle.sql.INTERVALDS";
    case -103:
        return "oracle.sql.INTERVALYM";
    case -102:
        return "oracle.sql.TIMESTAMPLTZ";
    case -101:
        return "oracle.sql.TIMESTAMPTZ";
    case -15:
    case -9:
    case 12:
        return "java.lang.String";
     ...
Run Code Online (Sandbox Code Playgroud)

但是,在较旧的OJDBC实现中,它看起来像这样:

    int arg1 = this.getColumnType(arg0);
    switch (arg1) {
    case -104:
        return "oracle.sql.INTERVALDS";
    case -103:
        return "oracle.sql.INTERVALYM";
    case -102:
        return "oracle.sql.TIMESTAMPLTZ";
    case -101:
        return "oracle.sql.TIMESTAMPTZ";
    case -15:
    case -9:
    case 1:
    case 12:
        return "java.lang.String";
    ...
Run Code Online (Sandbox Code Playgroud)

java.lang.String在后一种情况下,还有一个映射到的附加案例即.'情况1'.此"案例1"未映射到java.lang.String上面显示的第一个代码段中.

在更深入地看,这个'case 1'被映射到同一个类CHARgetColumnTypeName(int arg0 )方法中StructMetaData:

public String getColumnTypeName(int arg0) throws SQLException {
    int arg1 = this.getColumnType(arg0);
    int arg2 = this.getValidColumnIndex(arg0);
    switch (arg1) {
    case -104:
        return "INTERVALDS";
    case -103:
        return "INTERVALYM";
    case -102:
        return "TIMESTAMP WITH LOCAL TIME ZONE";
    case -101:
        return "TIMESTAMP WITH TIME ZONE";
    case -15:
        return "NCHAR";
    case -13:
        return "BFILE";
    case -9:
        return "NVARCHAR";
    case -2:
        return "RAW";
    case 1:
        return "CHAR";
 ...
Run Code Online (Sandbox Code Playgroud)

因此,如果我们使用OJDBC 7或OJDBC6 v12.1.0.1并指定CHAR列的数据类型,则以下代码将null在此列的索引的调用时返回:

 for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
     ...
     resultSetMetaData.getColumnClassName(columnIndex)
     ...
Run Code Online (Sandbox Code Playgroud)

如果我替换旧版本的OJDBC jar(例如:11.2.0.3),则相同的代码返回:java.lang.String.这是一个错误还是被设计删除了?以前有人遇到过同样的问题吗?

Ant*_*nio 1

接得好...!

\n\n

它确实看起来像一个错误;也许唯一反对的理由是,这将是甲骨文的一个令人难以置信的巨大忽视。

\n\n

专业错误:

\n\n\n\n

(注意第一行,与类型相关CHAR,映射到java.lang.String

\n\n
| SQL and PL/SQL Data Type | Oracle Mapping   | JDBC Mapping\n|------------------------- |------------------|-----------------------------------------------\n| CHAR, CHARACTER, LONG,   |                  | \n|STRING, VARCHAR, VARCHAR2 | oracle.sql.CHAR  | java.lang.String\n| NCHAR, NVARCHAR2         | oracle.sql.NCHAR | oracle.sql.NString \n| NCLOB                    | oracle.sql.NCLOB | oracle.sql.NCLOB \n
Run Code Online (Sandbox Code Playgroud)\n\n

对抗错误:

\n\n\n\n
\n

CHAR/NCHAR 实际上只不过是变相的 VARCHAR2/NVARCHAR2,这一事实使我认为实际上只有两种字符串类型需要考虑,即 VARCHAR2 和 NVARCHAR2。我从未在任何应用程序中发现 CHAR 类型的用途。由于 CHAR 类型总是将结果字符串空白填充到固定宽度,因此我们很快发现它在表段和任何索引段中消耗了最大的存储空间。这已经够糟糕的了,但是避免 CHAR/NCHAR 类型还有另一个重要原因:它们会在需要检索此信息的应用程序中造成混乱(许多应用程序在存储数据后无法 \xe2\x80\x9cfind\xe2\x80\x9d 数据) )。其原因与字符串比较的规则及其执行的严格性有关。....

\n
\n\n

[然后在同一篇文章中给出了一个很好的例子;非常值得一读]

\n\n

事实是CHAR并不能成为 Oracle 在没有明确通知的情况下破坏现有应用程序的理由;因此,它是一个错误的假设显然更合理。

\n\n

鉴于理论上它不会有缺点,作为一种极端的解决方法,您可能会更改所有涉及的表以将其 CHAR 类型重新定义为 VARCHAR2 (如果您有权这样做,并且这是可行的)。

\n