sql >> データベース >  >> RDS >> Oracle

ストアドプロシージャによって返されたSTRUCTから配列を読み取ります

    java.sql.SQLDataを実装するオブジェクトを作成します 。このシナリオでは、TEnclosureを作成します およびTAnimal どちらもSQLDataを実装するクラス 。

    参考までに、新しいOracle JDBCバージョンでは、oracleなどのタイプがあります。 .sql.ARRAY java.sqlを優先して非推奨になりました 種類。 java.sqlのみを使用して配列(以下で説明)を作成する方法はわかりませんが API。

    readSQL()を実装する場合 フィールドを順番に読みます。 java.sql.Arrayを取得します sqlInput.readArray()を使用 。したがって、TEnclosure.readSQL() このようになります。

    @Override
    public void readSQL(SQLInput sqlInput, String s) throws SQLException {
        id = sqlInput.readBigDecimal();
        name = sqlInput.readString();
        Array animals = sqlInput.readArray();
        // what to do here...
    }
    

    注:readInt() も存在しますが、OracleJDBCは常にBigDecimalを提供しているようです。 NUMBERの場合

    java.sql.Arrayなどの一部のAPIに気付くでしょう。 タイプマップをとるメソッドがありますMap<String, Class<?>> これは、SQLDataを実装する対応するJavaクラスへのOracleタイプ名のマッピングです。 (ORAData うまくいくかもしれませんか?)

    Array.getArray()を呼び出すだけの場合 、Structを取得します JDBCドライバーがConnection.setTypeMap(typeMap)を介してタイプマッピングを認識していない限り、オブジェクト 。ただし、接続にtypeMapを設定しても機能しなかったため、getArray(typeMap)を使用します。

    Map<String, Class<?>> typeMapを作成します どこかに、タイプのエントリを追加します:

    typeMap.put("T_ENCLOSURE", TEnclosure.class);
    typeMap.put("T_ANIMAL", TAnimal.class);
    

    SQLData.readSQL()内 実装、sqlInput.readArray().getArray(typeMap)を呼び出します 、Object[]を返します ここで、Object エントリまたはタイプTAnimal

    もちろん、List<TAnimal>に変換するコード 面倒になるので、このユーティリティ関数を使用して、nullと空のリストポリシーまで必要に応じて調整してください:

    /**
     * Constructs a list from the given SQL Array
     * Note: this needs to be static because it's called from SQLData classes.
     *
     * @param <T> SQLData implementing class
     * @param array Array containing objects of type T
     * @param typeClass Class reference used to cast T type
     * @return List<T> (empty if array=null)
     * @throws SQLException
     */
    public static <T> List<T> listFromArray(Array array, Class<T> typeClass) throws SQLException {
        if (array == null) {
            return Collections.emptyList();
        }
        // Java does not allow casting Object[] to T[]
        final Object[] objectArray = (Object[]) array.getArray(getTypeMap());
        List<T> list = new ArrayList<>(objectArray.length);
        for (Object o : objectArray) {
            list.add(typeClass.cast(o));
        }
        return list;
    }
    

    配列の書き込み

    配列の記述方法を理解するのはイライラしました。OracleAPIは配列を作成するために接続を必要としますが、writeSQL(SQLOutput sqlOutput)のコンテキストでは明確な接続がありません。 。幸い、このブログ OracleConnectionを取得するためのトリック/ハックがあります 、ここで使用しました。

    createOracleArray()を使用して配列を作成する場合 リストタイプを指定します (T_ARRAY_ANIMALS )タイプ名の場合、単一のオブジェクトタイプではありません。

    配列を書くためのジェネリック関数は次のとおりです。あなたの場合、listType "T_ARRAY_ANIMALS"になります List<TAnimal>を渡します

    /**
     * Write the list out as an Array
     *
     * @param sqlOutput SQLOutput to write array to
     * @param listType array type name (table of type)
     * @param list List of objects to write as an array
     * @param <T> Class implementing SQLData that corresponds to the type listType is a list of.
     * @throws SQLException
     * @throws ClassCastException if SQLOutput is not an OracleSQLOutput
     */
    public static <T> void writeArrayFromList(SQLOutput sqlOutput, String listType, @Nullable List<T> list) throws SQLException {
        final OracleSQLOutput out = (OracleSQLOutput) sqlOutput;
        OracleConnection conn = (OracleConnection) out.getSTRUCT().getJavaSqlConnection();
        conn.setTypeMap(getTypeMap());  // not needed?
        if (list == null) {
            list = Collections.emptyList();
        }
        final Array array = conn.createOracleArray(listType, list.toArray());
        out.writeArray(array);
    }
    

    注:

    • ある時点で、setTypeMapと思いました。 必須でしたが、その行を削除してもコードは機能するため、必要かどうかはわかりません。
    • nullまたは空の配列を書き込む必要があるかどうかはわかりませんが、空の配列の方が正しいと思いました。

    Oracleタイプのヒント

    • Oracleはすべてを大文字にするため、すべての型名は大文字にする必要があります。
    • SCHEMA.TYPE_NAMEを指定する必要がある場合があります タイプがデフォルトのスキーマにない場合。
    • grant executeを忘れないでください 接続しているユーザーが所有者でない場合は、型について。
      パッケージに対して実行したが、型ではない場合は、getArray() タイプメタデータを検索しようとすると、例外がスローされます。

    を使用する開発者向け 、 SpringDataJDBC拡張機能を確認することをお勧めします。 SqlArrayValueを提供します およびSqlReturnArraySimpleJdbcCallの作成に役立ちます 配列を引数として取るか、配列を返すプロシージャの場合。

    7.2.1INパラメータにSqlArrayValueを使用してARRAY値を設定する 配列パラメータを使用してプロシージャを呼び出す方法について説明します。



    1. mysqlの手順の何が問題になっていますか?

    2. mysqlでの奇妙なキャスト動作

    3. Oracle:CSVファイルをインポートします

    4. 同じサーバー上のデータベース間でユーザー権限をコピーする