ユーザ定義型に対応したいなら、DatabaseMetaDataは、使えません。
昨日のエントリーに書いたようなストアドプロシージャを、
S2DaoのPROCEDUREアノテーションを使って呼び出すと、
どういう問題が発生するのか?
こんなDaoを書いてアクセスしてみる。
package examples.dao; import java.util.Map; public interface StoredTypeTestDao { public Class BEAN = Employee.class; public String getNewPerson_PROCEDURE = "NEW_PERSON"; public Map getNewPerson(Integer id, String name); public String getPersonName_PROCEDURE = "PERSON_NAME"; public Map getPersonName(Person person); public String getNewPersonArray_PROCEDURE = "NEW_PERSON_ARRAY"; public Map getNewPersonArray(Integer id1, String name1, Integer id2, String name2); public String getPersonNameMerge_PROCEDURE = "PERSON_NAME_MERGE"; public Map getPersonNameMerge(Person[] personArray); }
(クライアント側のソースは省略)
このDaoのいずれかのメソッドを呼び出すと、
org.seasar.dao.handler.AbstractBasicProcedureHandler#bindArgsメソッド内で
SQLRuntimeExceptionが発生する。
問題発生箇所は、値をcall文に設定している所。
for (int i = 0; i < columnTypes.length; i++) { if (isOutputColum(columnInOutTypes[i].intValue())) { ps.registerOutParameter(i + 1, columnTypes[i].intValue()); } if (isInputColum(columnInOutTypes[i].intValue())) { ps.setObject(i + 1, args[argPos++], columnTypes[i].intValue()); } }
ここで、ユーザ定義型や配列を設定する際に、
columnTypes[i].intValue()の値として「1111」が渡されるから、
型が合わず、SQLRuntimeExceptionが発生しているらしい。
ちなみに1111とは、「java.sql.Types.OTHER」の値で、
要は「カラムの型がよく分からない」ってこと。
ところで、
S2Daoは、Daoの初回アクセス時にDBMSからメタデータを取得し、
それを使って型変換を行なったり、引数の数を決めて、SQL文を作成している。
そう、
OracleのJDBCドライバを使っていると、
DatabaseMetaData#getProcedureColumnsで
ストアドプロシージャの戻り値や引数を確認しようとすると、
ユーザ定義型や配列は、すべて「1111 (java.sql.Types.OTHER)」になっちゃう、ってこと。
なので、DatabaseMetaDataを利用するだけでは、
ストアドプロシージャの引数や戻り値に使われている型の詳細が分からない。
2007/03/24追記。
DatabaseMetaData#getProcedureColumnsには型名も入っているし、
DatabaseMetaData#getUDTsを使えば、型の詳細はもうちょっと分かります
じゃぁどうするか。
うん、自前でSQLを発行して、型の情報を取ってしまおう。