3

こんな状況です

jOOQでは、JDBC を抽象化する必要がたくさんあります。一部のデータは単純な ResultSet から取得され、一部のデータは SQLInput (UDT の場合)、または CallableStatements (ストアド プロシージャ/関数の場合) から取得されます。したがって、これらの JDBC タイプに抽象化を追加したいと思います。

java.sql.ResultSet
java.sql.CallableStatement
java.sql.SQLInput
java.sql.SQLOutput

現在、それらはすべてほぼ同じように機能します。通常、のすべてのデータ型に対してgetandメソッドがあります。たとえば、次のような方法で出荷されますsetjava.sql.Types

BigDecimal getBigDecimal(int index);
int getInt(int index);

そして、それらはすべて次のようなメソッドを持っています

boolean wasNull();

問題

残念ながら、これらの JDBC インターフェイスは単一の共通インターフェイスを拡張するものではなく、このスニペットのような一般的な JDBC コードを記述したい人にとっては簡単です (私の質問をサポートするための単なる例です)。

// As JDBC has no support for BigInteger types directly,
// read a BigDecimal and transform it to a BigInteger
BigDecimal result = null;

if (source instanceof ResultSet) {
    result = ((ResultSet) source).getBigDecimal(index);
}
else if (source instanceof CallableStatement) {
    result = ((CallableStatement) source).getBigDecimal(index);
}
else if (source instanceof SQLInput) {
    result = ((SQLInput) source).readBigDecimal();
}

return result == null ? null : result.toBigInteger();

ResultSet上記のコードは、 、CallableStatement、の 3 つすべてに対して記述する必要がありますSQLInput。そして、似たような例がたくさんあります

私の質問は

  • この問題をエレガントに解決する JDBC 拡張ライブラリを知っている人はいますか?
  • それとも、これらすべてのタイプの単純なラッパー クラス (またはアダプター) を自分で作成する必要がありますか?
  • それとも、その事実を受け入れて、内部ライブラリ コードを複製し続けますか?

どのソリューションを好みますか、またその理由は何ですか? フィードバックをお寄せいただきありがとうございます

4

3 に答える 3

3
  • この問題をエレガントに解決する JDBC 拡張ライブラリを知っている人はいますか?

いいえ、誰かがそれを発明する必要があります。


  • それとも、これらすべてのタイプの単純なラッパー クラス (またはアダプター) を自分で作成する必要がありますか?

私は間違いなくこれに行きます。共通のラッパー インターフェイスから始めます。

public interface DataProvider {
    public BigInteger getBigInteger(int columnIndex);
    // ...
}

すべての具体的なラッパーに実装させます。

public class ResultSetDataProvider implements DataProvider {
    private ResultSet resultSet;

    public ResultSetDataProvider(ResultSet resultSet) {
        this.resultSet = resultSet;
    }

    public BigInteger getBigInteger(int columnIndex) {
        BigDecimal bigDecimal = resultSet.getBigDecimal(columnIndex);
        return bigDecimal != null ? bigDecimal.toBigInteger() : null;
    }

    // ...
}

そして、代わりにそれを使用してください。

try {
    // Acquire ResultSet.
    DataProvider dataProvider = new ResultSetDataProvider(resultSet);
    // Process DataProvider.
} finally {
    // Close ResultSet.
}

  • それとも、その事実を受け入れて、内部ライブラリ コードを複製し続けますか?

いいえ、私はしません。コードをDRYにしてください。

于 2010-12-19T14:50:00.233 に答える
1

個人的にはそんなものは使いません。この抽象化によって、あなたが私の人生をずっと楽にしてくれているとは思いません。

SQL抽象化が永続層からリークする理由はないと思います。呼び出しを行い、オブジェクトにマップして、SQL抽象化を閉じます。あなたは彼らに固執してもらいたいように聞こえますが、それは悪い考えです。

Springの人々は、JDBCの使用を可能な限り簡単にしたと思います。私は間違っている可能性がありますが、あなたが提案している道を進む理由はわかりません。

SQLInputのjavadocsを見ると、次のようになっています。

カスタムマッピングにのみ使用されるこのインターフェイスは、バックグラウンドでドライバーによって使用され、プログラマーがSQLInputメソッドを直接呼び出すことはありません。

このインターフェースを公開する必要がある理由がわかりません。

ResultSetとCallableStatement(または、さらに言えば、任意のステートメント)に関しては、これらは最終的に1つ以上のResultSetを返し、クエリ結果を返すことができます。私はむしろその周りの抽象化を見たいと思います。私はあなたが他の人をさらすことによって水を濁していると信じています。私はそれをお勧めしません。

おそらく、それが行われたことがないという事実は、それが行われるべきではないという別の兆候です。しかし、あなたはそれをして、市場があなたに勝者を投票するかどうか見ることを歓迎します。

于 2010-12-19T16:39:36.497 に答える
0
  1. JDBC の拡張機能が不明です。
  2. デザインの残りの部分によっては、ラッパー クラスまたはビジター パターンが役立つ場合があります。
  3. それぞれを拡張し、同じメソッド シグネチャを持つ同じインターフェイスを実装して、必要なデータを取得するのはどうでしょうか。
于 2010-12-19T14:17:59.907 に答える