谷本 心 in せろ部屋

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

引数がArrayのストアドプロシージャ

本日最後、引数がArrayのストアドプロシージャ。
これがちょっと面倒くさい。


まずはストアドプロシージャ定義から。
配列で渡されたPersonの名前を結合するだけ。

CREATE OR REPLACE FUNCTION "PERSON_NAME_MERGE"
(
  USERS in PERSON_ARRAY
)
return VARCHAR2
is
begin
  return USERS(1).NAME || USERS(2).NAME;
end;
/


それを扱うJavaソース。

package examples.dao;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.Types;

import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;

import org.seasar.extension.dbcp.ConnectionPool;
import org.seasar.extension.dbcp.ConnectionWrapper;
import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.S2ContainerFactory;

public class StoredArrayArgClient {
	private static final String PATH = "j2ee.dicon";

	public static void main(String[] args) throws Exception {
		S2Container container = S2ContainerFactory.create(PATH);
		container.init();
		ConnectionPool pool = (ConnectionPool) container
				.getComponent(ConnectionPool.class);
		Connection conn = pool.checkOut();

		Person person1 = new Person();
		person1.setId(Integer.valueOf(100));
		person1.setName("USER1");
		Person person2 = new Person();
		person2.setId(Integer.valueOf(200));
		person2.setName("USER1");

		conn = ((ConnectionWrapper) conn).getPhysicalConnection();
		ArrayDescriptor ad = new ArrayDescriptor("PERSON_ARRAY", conn);
		ARRAY array = new ARRAY(ad, conn, new Object[] { person1, person2 });

		CallableStatement stmt = conn
				.prepareCall("{? = call PERSON_NAME_MERGE(?)}");
		stmt.registerOutParameter(1, Types.VARCHAR);
		stmt.setObject(2, array, Types.ARRAY);

		stmt.execute();

		Object o = stmt.getObject(1);
		System.out.println(o);
	}
}

何が面倒くさいって、
まずはConnectionWrapperのままArrayDescriptorをnewすると
ClassCastExceptionが発生しちゃうところ。
仕方なく物理コネクションを取得して、渡しています。


もう一つ面倒くさいのは、ArrayDescriptorがここに現れてしまう所。
Structは、Javaのクラスと、ちょうど1対1の関係になるから、
Javaのクラス(Person.class)にStructDescriptorを配置できたんだけど、、、
Arrayは、Java配列をクラス化したような存在なので、
どこにArrayDescriptorを置けば良いのか、ちょっと決めづらい。


まぁ、ぼちぼち決めていこう。