[Seasar-user:16110] Re: [S2JDBC] innerJoin と leftOuterJoin で同じ Entity を指定したい

Koichi Kobayashi [E-MAIL ADDRESS DELETED]
2008年 10月 25日 (土) 11:30:32 JST


小林 (koichik) です.

出かける支度中で慌て気味なので変なこと
書いてるかもしれませんがご容赦ください.

Date:    Sat, 25 Oct 2008 09:53:23 +0900
From:    Shotaro Tsubouchi <[E-MAIL ADDRESS DELETED]>
To:      [E-MAIL ADDRESS DELETED]
Subject: [Seasar-user:16109] [S2JDBC] innerJoin と leftOuterJoin で同じ Entity を指定したい

> 親子関係にある Entity、Foo と Baa において、
> ID が 1 の Baa を持っている Foo を取得し、
> その Foo 毎に関連する Baa も取得したい場合、

ここで「ID が 1 の Baa を持っている」は
結合条件ではなく選択条件なので,

> select() // jdbcManager.from(Foo.class)
>     .innerJoin(baaList(), false, eq(baaList().baaId(), 1))
>     .leftOuterJoin(baaList())
>     .getResultList();

と JOIN ON 〜 で条件を指定するのではなく,
WHERE で指定すべきかと.

となると EXISTS または IN で相関福問い合わせを
使うことになりますが,S2JDBC の SimpleWhere は
サポートしていないので,where(String, Object...) を
使うことになってしまいます.

相関福問い合わせは SQL だと

〜 where exists (select * from BAA where BAA_ID = ? and FOO_ID = T1_.FOO_ID)

みたいになります.
# この例は多対多関連なので本当は FOO_ID なんて
# ないのかもしれませんが.

ここで T1_ は主問い合わせの Foo のエイリアスで,
S2JDBC が割り振るものです.
S2JDBC は where(String, Object...) に渡された
文字列にこのエイリアスを自動的に割り振るので
T1_ は省略できます.

select() // jdbcManager.from(Foo.class)
    .innerJoin(baaList())
    .getResultList();
    .where("exists (select * from BAA  where BAA_ID = ? and FOO_ID = fooId", 1)
    .getResultList();

のようになるかと思うのですが,試してないので
怪しいかも.
カラム名とプロパティ名が入り乱れて気持ち悪い...


> ひとまず、AutoSelectImpl の 774 行目をコメントアウトして
> 例外を無視してみたところ、想定していたクエリーを発行できました。
> 結合条件の重複チェックが、innerJoin と leftOuterJoin で
> 分かれていれれば良いんですかね?

このケースで片方が leftOuterJoin なのは作為的な
気がします.(^^;

制約をゆるめるなら,フェッチしない結合は重複を
許すということが考えられますが,フェッチしない
ということは選択条件のためということになり,
それなら WHERE 句で頑張るのが筋かなと.
そのためには相関福問い合わせのサポートを向上する
必要があって悩ましいですが.


-- 
<component name="koichik">
    <property name="fullName">"Koichi Kobayashi"</property>
    <property name="email">"[E-MAIL ADDRESS DELETED]"</property>
    <property name="blog">"http://d.hatena.ne.jp/koichik"</property>
</component>



Seasar-user メーリングリストの案内