現在比較中2
dbfluteとS2JDBCについて、前回は生成やら管理部分を中心に見てみたが、
今回は使用感を中心に。
まぁ明らかに個人的な感想ですのでご容赦を。
最終的な結果としては比較するものじゃないかも?という気もしますが、
2008/11/18利用例や、S2JDBC-Genの次期対応について追記
AND検索
AND検索に関してはともにタイプセーフですが、
部品を組み合わせて、条件を作っていくS2JDBCよりは、
条件を組み合わせていくdbfluteの方が一歩リードかもしれません。
また、レコードが存在しない場合に例外を投げるようなメソッドも便利です。
(特に例外によりロールバックなどのトランザクション制御が多いと思うので)
追記(id:koichikさんよりのご指摘)
→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→
disallowNoResult()
の指定により、S2JDBCでも例外が投げられるとのこと。
条件() .disallowNoResult() .getResultList();
←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←
また、ConditionBean#toDisplaySql()
による表示機能がとっても便利で、内容も確認しやすいです。
まぁS2JDBCの方は、整形さえしっかりすれば、ソースのままでも確認しやすいかもしれないですが・・・
検索について1例
select() .where( and( //$でlike escape contains(empName(), "I"), eq(deptId(), 1) ) ) .getResultList(); //and()は省略可能
EmpCB cb = new EmpCB(); LikeSearchOption likeSearchOpt = new LikeSearchOption(); //escape文字を指定可能 likeSearchOpt.escapeByPipeLine(); likeSearchOpt.likeContain(); cb.query().setEmpName_LikeSearch("I", likeSearchOpt); cb.query().setDeptId_Equal(1); //cb.query().setEmpName_LikeSearch("I", likeSearchOpt) // .setDeptId_Equal(1); //とも出来る。 ListResultBean<Emp> list = empBhv.selectList(cb);
ただS2JDBCの検索系に関して、
existsなどのサブクエリをタイプセーフに書けるか?
によります。書けないようだとちょっとマイナスです。
軽く調べたところだと見当たらなかったので・・・条件付Aとしました。
追記
残念ながら現在のところは非対応とのこと。今後に期待
OR検索
Or検索に関してはdbfluteはばっさりと対応していません。
※いくらかの業務的に必要と思われるような例外は除く(like検索とか)
なので基本的にはUnionで対応することになります。
S2JDBCに関しては特に制限がなく普通に利用可能です。
select() .where( or( contains(empName(), "I"), eq(deptId(), 1) ) ) .getResultList();
EmpCB cb = new EmpCB(); LikeSearchOption andlikeSearchOpt = new LikeSearchOption(); andlikeSearchOpt.likeContain(); cb.query().setEmpName_LikeSearch("I", andlikeSearchOpt); cb.union(new UnionQuery<EmpCB>() { public void query(EmpCB unionCB) { unionCB.query().setDeptId_Equal(1); } }); ListResultBean<Emp> list = empBhv.selectList(cb);
制約がない場合の結合
Entityにアノテーションとフィールドを適切に設定すれば動くS2JDBCが素晴らしいのですが、
gen-ddlタスクなどにより、DBに制約を設定してしまうのは致命的。
次のバージョンより対応とのこと
Gen-Ddlで外部キー制約の生成を制御する - taediumの日記
//Emp.java @ManyToOne @JoinColumn(name="dept_Id", referencedColumnName="id") public Dept dept; //Dept.java /** empList関連プロパティ */ @OneToMany(mappedBy = "dept") public List<Emp> empList; //利用 select().innerJoin("dept").getResultList(); /* * 独自で定義したので、EmpNamesには定義がないので文字列で指定していますが、 * FKのあるDBより生成した場合はちゃんと生成されるし、 * 今回のように、Entityにだけ定義した場合にはgen-namesタスクにより再度生成することが可能とのこと */
dbfluteに関しては、設定ファイル(additionalForeignKeyMap.dfprop)
により、仮想的なキーを作成して、制約があるようにソースを生成してくれるのでDBは汚さない。
map:{ ; FK_EMP1 = map:{ ; localTableName = EMP ; foreignTableName = DEPT ; localColumnName = DEPT_ID ; foreignColumnName = ID } } //利用 EmpCB cb = new EmpCB(); //部署も合わせて取得 cb.setupSelect_Dept();//ここが生成される。 ListResultBean<Emp> list = empBhv.selectList(cb);
どちらにせよ、制約はちゃんとつける前提でいるのが無難
また、S2JDBCでも、Entity→DBという変更のタスクを利用しないなら問題なし。
結合
ON句に条件を加えたり、JOIN種類を変更する場合
dbfluteに関しては、
NOT NULL制約のない外部キー以外の結合はLEFT JOINになってしまうなどいくらかの制限がある。
ただし、基本的に結合するための条件なのか、レコードを絞るための条件なのか?
を考えると上記整理は基本的に問題はない。
S2JDBCには特に制限がなく自由に結合条件を指定でき、LEFT JOIN、INNER JOINなど自由に記述出来る。
自由度という点ではS2JDBCで、
きっちりと出来ること出来ないことが整理されているのがdbfluteといった感じ。
出来ないことというのは大概が方法として間違っていることだったりもしますが・・・
で、どうしてもできないようなことなどは外出しSQLになっていくということになります。
(
結合に関しては親テーブルの親テーブルまでといった制限などもあります。)
query().setUpOya().withOyanoOya();
追記(id:jfluteさんよりの指摘)
→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→
現在はいくらでもいけるとのこと。すばらしい・・・
←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←
外出しSQLについては以下(S2Daoとの比較)
http://dbflute.sandbox.seasar.org/contents/topic/compwiths2dao.html
※上記ページにない以下の様な機能の方が興味をそそるかもしれません。
バインド変数をMapでたどれる
埋め込変数コメント
Sql2Entity
Paging
Like検索のEscape
outside-sql-test
などなど盛りだくさんだったりします。
学習コスト
多分S2JDBCの方が学習コストが安いです。
基本的な部分だけだと、dbfluteも簡単ではありますが・・・
メソッドやら覚えることがあるので、ほぼSQLそのままに見えるS2JDBCにアドバンテージ。
さらに、dbfluteは出来ることがいろいろと多いので底が見えません。
更新系
dbfluteの場合、SELECT→UPDATEとしなくても、
IDとVersionNoさえわかれば更新が可能です。
(設定したプロパティのみ更新対象とする)
S2JDBCの場合
Emp emp = new Emp(); emp.id = 9l; emp.versionNo = 1; emp.sal = BigDecimal.valueOf(6000); //エラーとなる。 empService.update(emp); System.out.println(emp); emp = empService.findById(9l); System.out.println(emp);
※excludesNullとか、includesとかの指定で可能ではありますので、
Service側にそのようなメソッドを用意しておくことで対応が可能です。
dbfluteの場合
//[Emp: _id: 9 _empNo: 7839 _empName: KING _mgrId: null _hiredate: 1981-11-17 00:00:00.0 _sal: 5000.00 _deptId: 1 _versionNo: 1 ] Emp emp = new Emp(); emp.setId(9); emp.setVersionNo(1); emp.setSal(BigDecimal.valueOf(6000)); empBhv.update(emp); System.out.println(emp); //[Emp: _id: 9 _empNo: null _empName: null _mgrId: null _hiredate: null _sal: 6000 _deptId: null _versionNo: 2 ] emp = empBhv.selectByPKValueWithDeletedCheck(9); System.out.println(emp); //[Emp: _id: 9 _empNo: 7839 _empName: KING _mgrId: null _hiredate: 1981-11-17 00:00:00.0 _sal: 6000.00 _deptId: 1 _versionNo: 2 ]
可能。
一覧表示をして、更新機能を呼ぶ際などには便利なのではないでしょうか。
総評
dbflute
- ソースが生成されるdbfluteの方が安心感があります。
- テンプレートなども結構簡単にいじれます。
- 細かいオプションがたくさんあり、細かく制御できます。
- 大規模になればなるほど、生成されるソース量などdbfluteはネックになるかもしれません。(別管理でjarとして開発チームに提供するなど工夫が必要かも)
- アホなConditionBeanが組み立てられないようになっているのである程度のレベルが確保できるかもしれません。
- 外出しSQLを利用する際に便利な拡張があるので助かることがあるかもしれません。
- ログなどいろいろとシンプルです。
- id:jfluteさんの肩にすべてが掛かっています。
- 自動生成されたソースに関してはテストしなくていいといった確約を取っておかないと泣くことになるかもしれません。
- ページングが便利です。
- id:jfluteさんのブログ検索がFAQになっています。
S2JDBC
- 自由度が高いです。
- 管理方はこれからかもしれません。id:taediumさんが頑張っています。
- 使う分には十分な機能をそろっています。
- 中の方がよく見えないです。
- 拡張できる自信がありません。
- 流行ってる気がします。(Seasar界隈)
- ちょっといじっただけの私がわかったようなことを語っています(語れています)
- 良くも悪くも薄い気がします。
まとめ
無理やりの総評としては、
自由度の高いS2JDBC
厳密で気の利いた機能がちょこちょこあるdbfluteといった感じでしょうか。
視点としては、
管理者が安心出来るdbflute
現場が自由にやれるS2JDBC
かな?
最後に
なんにせよ、プロジェクトに適応出来る、出来ないの見極めが重要です。