@Procedure と @PrecedureCall の動きが違う件

仕事で S2Dao を弄ってたら、なんか挙動がおかしいなーと思ったので調べてみた!


S2Dao を使ってプロシージャコールをする場合は @ProcedureCall を使うようですが、うちのシステムで動かしてみたら例外が throw されちゃいました。
ちなみに対象のプロシージャは、システム日付からあるテーブルのデータをもとに差分を出して返すという、簡単に言ったらテスト用に日付を進ませたり戻したりできるようなプロシージャがあるんです。
使い方は普通の SYSDATE と似た感じで、

SELECT U_SYSDATE() FROM DUAL;

みたいな感じで取り出せるようになってます。
この状態で DAO に下記のように @ProcedureCall をつける。

import java.util.Date;

import org.seasar.dao.annotation.tiger.ProcedureCall;
import org.seasar.dao.annotation.tiger.S2Dao;

@S2Dao(bean = Hoge.class)
public interface HogeDao {

    @ProcedureCall("U_SYSDATE")
    public Date getSysDate();

}

これで実行したら…なんか内部で Oracle エラーが出てしまった。番号までは失念したので書けませんが。
この状態で、試しに @ProcedureCall から @Procedure に変えて動かしてみました。

    @Procedure("U_SYSDATE")
    public Date getSysdate();

そしたら、メタデータを拾ってるのか時間はかかりましたが、ばっちり拾えました。
なんでかなーっと、よく調べてみたら @ProcedureCall の方は CallableStatement に渡してる SQL

{call U_SYSDATE ()}

こんな感じで、頭に "? = " がついてなかったんですよね。
仕方がないから、下のような適当な DTO を作って、

import java.util.Date;

import org.seasar.dao.annotation.tiger.ParameterType;
import org.seasar.dao.annotation.tiger.ProcedureParameter;

public class SysDate {

    @ProcedureParameter(ParameterType.RETURN)
    Date sysDate;

    // getter/setter 省略

}

DAO の方を下記のように書き直してやれば、

    @ProcedureCall("U_SYSDATE")
    public void getSysdate(SysDate dto);

ちゃんと動いてくれました。


理屈としては、@ProcedureCall は実際のDBメタデータを見ないから、っていうのはわかるんだけど…。
いちいち DTO を作って引数に渡して、みたいなことをやらずに、DAO 側でアノテーションを用意して @Procedure みたいに返り値だけ書く、っていうことやらないのかなぁ〜。
自分で作れって話?w