谷本 心 in せろ部屋

はてなダイアリーから引っ越してきました

ユーザ定義型に対応したいなら、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文を作成している。


そう、
OracleJDBCドライバを使っていると、
DatabaseMetaData#getProcedureColumnsで
ストアドプロシージャの戻り値や引数を確認しようとすると、
ユーザ定義型や配列は、すべて「1111 (java.sql.Types.OTHER)」になっちゃう、ってこと。


なので、DatabaseMetaDataを利用するだけでは、
ストアドプロシージャの引数や戻り値に使われている型の詳細が分からない。

2007/03/24追記。
DatabaseMetaData#getProcedureColumnsには型名も入っているし、
DatabaseMetaData#getUDTsを使えば、型の詳細はもうちょっと分かります

じゃぁどうするか。


うん、自前でSQLを発行して、型の情報を取ってしまおう。