2016-05-19 7 views
5

OJDBCの仕事の1つは、Oracleデータ型をJava型にマップすることです。OJDBC 7がCHARデータ型をJava文字列にマップしないのはなぜですか?

ただし、CHARデータ型を指定すると、java.lang.Stringにはマッピングされません。この動作を示すバージョンは、OJDBC7 v12.1.0.2およびOJDBC6 v12.1.0.1です。以前のバージョンでは、CHARのデータ型は実際にjava.lang.Stringにマップされていました。

深く掘り下げて調べると、Oracleデータ型からJava型へのマッピングを実装するOJDBCパッケージStructMetaDataがOWDBCのoracle.jdbc.driverパッケージ内に存在することが発見されました。その中にメソッドがあります: 'getColumnClassName(int arg0)'は注意が必要です。私たちは、次のようにOJDBC v7のため、java.lang.Stringにマッピングされた例があることに気づい: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 1: 
    case 12: 
     return "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"; 
    ... 

はしかし、古いOJDBCの実装の中に、それはこのように見えました後者の場合、すなわち、 'ケース1'。この 'ケース1'は、上記の最初のコードスニペットのjava.lang.Stringにはマッピングされません。このため

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"; 
... 

、我々はOJDBC 7またはOJDBC6 v12.1.0.1使用している場合:深いご覧の上、

は、この「ケース1」と同じStructMetaDataクラスのgetColumnTypeName(int arg0)メソッド内CHARにマッピングされていますそして、列のデータ型としてCHARを指定し、次のコードは、この列のインデックスのための呼び出しにnullを返します。

for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) { 
    ... 
    resultSetMetaData.getColumnClassName(columnIndex) 
    ... 

私は例えば(OJDBCジャーの古いバージョンを交換する場合: 11.2.0.3)、同じコードが返されます:java.lang.String。これはバグですか?それとも設計上削除されましたか? 前に誰かが同じ問題に直面したことがありますか?

+1

ドライバのリリースノートを確認しましたか?これが間違っていると思われる場合は、My Oracle SupportでSRを開きます。私は提供されたソリューションに最も満足していました。 –

答えて

0

良いキャッチ...!

これは本当にバグのようです。おそらく唯一の議論は、オラクルが信じられないほど大きな見通しになることです。

プロバグ:

  • 後方互換性の問題。JDBCドライバの更新は、JPublisher Data Type and Java-to-Java Type Mappings約明示的
  • CHAR宣言にこのノートを依存している既存のアプリケーションを破壊するであろう12C

のようにマッピングを記述する(これは、CHARタイプに関連し、最初の行に注意してくださいjava.lang.Stringにマップ)のバグに対する

| SQL and PL/SQL Data Type | Oracle Mapping | JDBC Mapping 
|------------------------- |------------------|----------------------------------------------- 
| CHAR, CHARACTER, LONG, |     | 
|STRING, VARCHAR, VARCHAR2 | oracle.sql.CHAR | java.lang.String 
| NCHAR, NVARCHAR2   | oracle.sql.NCHAR | oracle.sql.NString 
| NCLOB     | oracle.sql.NCLOB | oracle.sql.NCLOB 

  • オラクルは、サポートされているタイプからCHARを却下しようとしているという仮説を立てることができます。実際、CHARタイプはVARCHAR2よりも実際には利点がなく、いくつかの欠点はそれを選択しないことになります。過去には、 "CHAR"は、あらかじめ定義された固定長のアイテムを定義するという意図を他の開発者に伝えていますが、これを強制することさえありません。短い値)。 興味のある方は、優秀な本Expert Oracle Database Architecture - Oracle Database 9i, 10g, and | Thomas Kyte | Apressのトピックに専用のセクションがあります。

CHAR/NCHARは変装してVARCHAR2/NVARCHAR2以上のものが意見を私に行うものではありません実際にあるという事実を:あなたは著者が自分の著書を引用時点で、Ask Tom "Char Vs Varchar"に抜粋を読むことができますVARCHAR2とNVARCHAR2の2つの文字列型しか存在しないことに注意してください。どのアプリケーションでもCHAR型の使用が見つかりませんでした。 CHAR型は常に結果の文字列を固定幅に埋め込むので、テーブルセグメントとインデックスセグメントの両方で最大の記憶域を消費することがわかります。それは十分に悪いですが、CHAR/NCHAR型を避ける重要な理由がもう1つあります。この情報を取得する必要のあるアプリケーションで混乱を招きます(多くは保存後にデータを見つけることができません)。この理由は、文字列比較のルールとそれらが実行される厳密さに関係しているためです。 ....

[その後、同じ投稿でも大きな例が続きます。

CHARというのは、オラクルが既存のアプリケーションを破棄することを納得させるものではありません。それがバグであるという仮説は、はるかに賢明です。

理論的には、極端な回避策として、関連するすべての表を変更してCHARタイプをVARCHAR2として再定義することができます(実行する権限がある場合は実行可能です)。

関連する問題