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
を提供します およびSqlReturnArray
、SimpleJdbcCall
の作成に役立ちます 配列を引数として取るか、配列を返すプロシージャの場合。
章