谷本 心 in せろ部屋

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

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

続いて、引数がStructのストアドプロシージャの扱い方を考える。
PERSON型を渡して、PERSON.NAMEを返すようなプロシージャを定義する。

CREATE OR REPLACE FUNCTION "PERSON_NAME"
(
  USER in PERSON
)
return VARCHAR2
is
begin
  return USER.NAME;
end;
/


これに対応したJavaのソースは、以下の通り。

package examples.dao;

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

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

public class StoredTypeArgClient {
	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 person = new Person();
		person.setId(Integer.valueOf(100));
		person.setName("USER1");

		CallableStatement stmt = conn.prepareCall("{? = call PERSON_NAME(?)}");
		stmt.registerOutParameter(1, Types.VARCHAR);
		stmt.setObject(2, person, Types.STRUCT);

		stmt.execute();

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

さて、ここでPerson型をどう扱うべきか。
選択肢としては、

  • ORADataの実装 (toDatumメソッドを実装する)
  • SQLDataの実装 (getSQLTypeName, readSQL, writeSQLを実装する)

の2種類があるんだけど、ここでは簡単なORADataを選択する。


真面目にSQLDataを実装すれば、
OracleJDBCドライバに依存しなくて済むかも知れないんだけど
どうせ、Arrayを扱う時に、Oracleドライバに依存する事になるので。

package examples.dao;

import java.sql.Connection;
import java.sql.SQLException;

import oracle.sql.Datum;
import oracle.sql.ORAData;
import oracle.sql.STRUCT;
import oracle.sql.StructDescriptor;

public class Person implements ORAData {
	Integer id;

	String name;

	public Datum toDatum(Connection conn) throws SQLException {
		StructDescriptor sd = new StructDescriptor("PERSON", conn);
		STRUCT struct = new STRUCT(sd, conn,
				new Object[] { this.id, this.name });
		return struct;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

はい、これで、引数が正常に渡せて、戻り値も正しく取れました。