[Seasar-user:16120] Re: [S2JDBC] innerJoin と leftOuterJoin で同じ Entity を指定したい
Koichi Kobayashi
[E-MAIL ADDRESS DELETED]
2008年 10月 27日 (月) 05:30:19 JST
小林 (koichik) です.
Date: Mon, 27 Oct 2008 03:24:46 +0900
From: Shotaro Tsubouchi <[E-MAIL ADDRESS DELETED]>
To: [E-MAIL ADDRESS DELETED]
Subject: [Seasar-user:16117] Re: [S2JDBC] innerJoin と leftOuterJoin で同じ Entity を指定したい
> 等価ではありますが、パフォーマンス面を考えると、
> 意図は明確なのかもしれませんが、副問い合わせという選択は微妙に思えます。
> (最近のRDB事情に詳しくないので、的を得てない言及だったらごめんなさい。)
古い RDBMS っていうか古い Oracle だと,EXISTS は
インデックスさえ使われれば速かったですよ.
事実上結合しないので.
っていうか,inner join とか使えるようになったのは
Oracle だと (たしか) 9iR2 からで,結構新しいです.
> フェッチしない結合を WHERE で扱えている、というのは、
> これは、タイプセーフな記述ではないが、扱うことは可能という事でしょうか?
タイプセーフというのは S2JDBC-Gen が生成する
クラスを使った場合の話ですよね.
そういうことではなく,ここで書いたのは,S2JDBC
そのものの API の話です.
元々 S2JDBC としては innerJoin() 等で
追加の条件を指定することができなかったので,
例えば id が 1 の BAA を持っている FOO を
(BAA をフェッチせずに) 取得するには
select() // jdbcManager.from(Foo.class)
.innerJoin(baaList(), false)
.where(eq(baaList().id(), 1))
.getResultList();
と where() で指定するしかなかったのです.
当時は SimpleWhere を使ったので
select() // jdbcManager.from(Foo.class)
.innerJoin(baaList(), false)
.where(new SimpleWhere().eq("baaList.id", 1))
.getResultList();
となりますが,同じことです.
これがフェッチしない結合を where で扱えていると
いうことです.
innerJoin() で追加の条件を指定できるように
なったのは 2.4.22 からなので,それ以前から
使っていた人達はこういう指定をしているわけです.
> 今でも WHERE でやろうと思えばやれるが、
> JOIN でなら、重複さえ許せばタイプセーフでそのまま実現できるのではないか?
> ということが私の言いたいことです。
> (このことが全体的なパフォーマンス劣化に如実に影響するということなのであれば。
> 無理強いはしません。)
パフォーマンスは関係なくて,仕様の互換性と
整合性,わかりやすさの問題です.
> これを許してしまうと、
> WHERE で使えなくなったり、重複した時に使えなくなったりする、というのは
> どういう場合なのでしょうか?
select() // jdbcManager.from(Foo.class)
.innerJoin(baaList(), false)
.innerJoin(baaList())
.where(eq(baaList().id(), 1))
.getResultList();
と書かれた時の baaList().id() の解釈の問題です.
フェッチしない結合は where() で使えないことに
すれば 2 番目の結合であることが一意に決まりますが,
前述のように互換性を損ないます.
重複した時だけ,フェッチしない結合を where で
使えないことにすると,いかにも落とし穴のように
思えます.
上の例で,baaList().id() が下の innerJoin の
ものだとすぐに理解できるでしょうか?
> leftOuterJoin なのであれば結合条件だけど、
> innerJoin であるならば選択条件でしょ、ということですね。
全然違います.
結合そのものの条件は JOIN ON に書くべきで,
それを結合条件と書きました.
行を選択して減らす,そのための条件は WHERE 句で
書くべきで,それを選択条件と書きました.
そういう違い.inner/outer の違いは関係ありません.
結合条件とか選択条件とか勝手な用語を使ったのは
失敗でしたね.
わざとらしい例で言うと,名前を指定して従業員を
選択するのに,
select e1.*
from employee e1
inner join employee e2 on e1.id = e2.id and e2.name = 'HOGE'
なんて書かないですよね?
select *
from employee
where name = 'HOGE'
って書きますよね?
ここで name = 'HOGE' は選択のための条件です.
「ID が 1 の Baa を持っている Foo」というのも
これと「全く」同じで,選択のための条件です.
--
<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 メーリングリストの案内