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

Shotaro Tsubouchi [E-MAIL ADDRESS DELETED]
2008年 10月 27日 (月) 07:07:03 JST


ショータローこと坪内です。

> タイプセーフというのは S2JDBC-Gen が生成する
> クラスを使った場合の話ですよね.

そうです。
んー、そういう意味では S2JDBC というより S2JDBC-Gen に対する要望だったですね。

> そういうことではなく,ここで書いたのは,S2JDBC
> そのものの API の話です.

伝え方が悪くてすみませんが、
タイプセーフな記述で実現したいな、というのが私の要望だったので、
S2JDBC での元々の書き方については、申し訳ないですがどうでも良かったのです。。

> select() // jdbcManager.from(Foo.class)
>     .innerJoin(baaList(), false)
>     .innerJoin(baaList())
>     .where(eq(baaList().id(), 1))
>     .getResultList();
> 
> 上の例で,baaList().id() が下の innerJoin の
> ものだとすぐに理解できるでしょうか?

ようやく理解しました。
(そう言えば口頭で話していた時に聞いたような。。すみません。)
baaList().id() が下の innerJoin のものだとわかるよう、

    .where(eq(baaList(3).id(), 1))
                      ^
こんな感じに指定できるようにできたらどうか、ということを書いたのですが、
そもそもその指定が無かったら、確かにどれに対してかが解らないですね。

> 全然違います.
> 結合そのものの条件は JOIN ON に書くべきで,
> それを結合条件と書きました.
> 行を選択して減らす,そのための条件は WHERE 句で
> 書くべきで,それを選択条件と書きました.
> そういう違い.inner/outer の違いは関係ありません.

書き方が悪かったですね。そこは理解しているつもりです。
言いたかったのは、結合先に対する選択条件は WHERE 句に書くべきなんでしょうが、
書けるんだし JOIN ON に書いちゃってもまぁいいんじゃ、ということでした。

何にしても、整合性や、わかりにくさの問題があるので、
正式に採用みたいなのは無理そうですね。
独自に AutoSelectImpl を変更して使おうと思います。

長々とすみません。ありがとうございました。


Koichi Kobayashi さんは書きました:
> 小林 (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」というのも
> これと「全く」同じで,選択のための条件です.
> 
> 
> 


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