5

これは私が今抱えている特定の問題ではなく、頭を包み込むことができないものです. ここで質問やインターネット上の情報を見つけることができませんでした。

java.lang.Integer(プリミティブの)などのラッパー クラスintは、最初から Java に存在していました。しかし、JDBCの開発者は、 Java プリミティブgetIntを使用して、などのメソッドを実装することを選択しました。getLongプリミティブの問題は、それらが SQL を表現できないことNULLです。

この問題を回避するために、JDBC 開発者は、列が である場合にやなどのデフォルトのプリミティブ値を返す多くのメソッドを作成し、ユーザーが であると想定されているかどうかを確認する関数を導入しました。さらに悪いことに、 PreparedStatementなどの他の多くのメソッドがラッパー オブジェクトの代わりにプリミティブを受け入れ、ユーザーは対応する列を に設定するために条件付きで使用する必要があります。0falseNULLwasNull()null setIntsetNullNULL

これにより、ユーザーがJDBC API を使用する方法が不必要に複雑になっていることがわかりました。JDBC のResultSetオブジェクトが、列に SQL があるときにgetIntegerJavanullInteger オブジェクトNULLとして返すと、チェックの手間がかからず非常に便利でしwasNullた。Java のボックス化解除は、 Integerオブジェクトをintプリミティブ変数に割り当て、それを に変換する必要がある場合を自動的に処理し0ます。PreparedStatementにメソッドがある場合setInteger、ユーザーはこれを使用して適切な列 (SQL 値を含む) の値を設定するだけで、NULLnull にする必要があるかどうかを確認して元に戻すという面倒な作業は必要ありません。setNull.

現在でも、この異常を修正するために JDBC に変更は加えられていません。JDBC は、すでに Java 1.7 または 1.8 になった後もプリミティブ型を使用し続けます(そうですか?)。Java の組み込みのボックス化とボックス化解除により、プリミティブ型を想定して作成された古いアプリケーションは、ラッパーを使用するように更新されたバージョンの JDBC で引き続き正しく動作することが保証されます。では、プリミティブの代わりにラッパー オブジェクトを使用するように JDBC をアップグレードしようとする人が誰もいないのはなぜでしょうか?

PS: JDBC に関するこの無意味な問題に対する推奨される代替ソリューションを聞くことができれば幸いです。

4

2 に答える 2

5

あなたの質問に完全に答えるわけではありませんが、JDBC 1.2 仕様には次の「拒否された」設計上の選択肢が含まれています。

A.8 GetObject と getXXX
のサポート さまざまな get/set メソッドと一般的な getObject/setObject メソッドが重複しているため、get/set メソッドを破棄し、単純に getObject/setObject を使用することにしました。ただし、プログラマーが SQL 型を知っているという単純な一般的なケースでは、結果のキャストと抽出は非常に面倒です。
int i = ((Integer)r.getObject(1, java.sql.Types.INTEGER)).intValue()
したがって、このケースではミニマリストの原則を少し曲げて、さまざまな get/set メソッドを優先インターフェイスとして保持することにしました。大部分のアプリケーション プログラマは、ツール ビルダーや高度なアプリケーション用の getObject/setObject メソッドも追加します。

その仕様の第14章には、次のようにも書かれています。

たとえば、SQL INTEGER は通常 Java int にマップされます。これは、単純な Java 型として SQL 値を読み書きするための単純なインターフェースをサポートします。

そして第 2 章には次のように書かれています。

残りの Java システムと一貫性のある Java インターフェースを提供する

私が知る限り、ほとんどの Java API はラッパー型ではなくプリミティブ型を使用しています。

また、仕様の頃 (1.2 の日付は 1997 年 1 月 10 日) には、ボックス化とボックス化解除はなく、使用Integerなどはかなり面倒でした。たとえば、Integer直接数学を実行することはできません。実際に加算、乗算などの基本的な操作を実行する前に、まず を呼び出しintValue()て を取得する必要があります。次に、結果を に変換して保存する必要があります。これは、プリミティブにゲッターとセッターを用意する十分な理由のように思えます。intInteger

そして、この仕様が設計されたのは 1995 年から 1997 年の間のどこかであることを思い出してください。この時代は、メモリが比較的高価で、プリミティブのラッパー オブジェクトのメモリが単純に高かった時代です。単純なオブジェクトは 8 バイト + プリミティブ フィールドのサイズだと思います。int4 ではなく 12 バイトのコストである の場合。

于 2013-08-12T14:36:11.513 に答える
3

一言で言えば互換性。JDBC API は、オートボクシングのずっと前に公開されており、現在それを変更するには、すべてのサードパーティ ベンダーが JDBC 実装を更新してリリースする必要があります。これはロジスティクス上の悪夢であり、JDBC API を使用しているベンダーは、動作の変更に対応する必要があります。

このタイプの変更を行う明白な方法は、JDBC2 という新しい API をリリースすることですが、特に JPA/Hibernate がほとんどの一般的な使用法で低レベルの JDBC API を隠していることを考えると、IMHO JDBC はこれを保証するほど壊れています。 .

于 2013-08-12T11:11:38.803 に答える