Doma SQLテンプレートのしくみ
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

Doma SQLテンプレートのしくみ

  • 291 views
Uploaded on

Doma SQLテンプレートのしくみ

Doma SQLテンプレートのしくみ

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
291
On Slideshare
186
From Embeds
105
Number of Embeds
1

Actions

Shares
Downloads
1
Comments
0
Likes
0

Embeds 105

https://twitter.com 105

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Doma SQLテンプレートのしくみ by @nakamura_to
  • 2. @nakamura_to
  • 3. Domaとは ? 3
  • 4. DBアクセスライブラリ • コンパイル時のコード生成 & チェック • 2 Way SQL対応テンプレート • Java 8対応 • 依存ライブラリなし
  • 5. デモ 5
  • 6. DAOインタフェース example/EmployeeDao.java @Dao(config = AppConfig.class) public interface EmployeeDao { @Select Employee selectById(Integer id); }
  • 7. SQLファイル META-INF/example/EmployeeDao/selectById.sql select * from employee where id = /* id */0
  • 8. コンパイル • SQLファイルの存在チェック • バインド変数のマッピングチェック • DAO実装クラスの生成
  • 9. 実行 EmployeeDao employeeDao = new EmployeeDaoImpl(); Employee result = employeeDao.selectById(1); select * from employee where id = ?
  • 10. Domaの系譜 10
  • 11. S2Dao (2004) DBFlute (2006) JPA (2006) S2JDBC (2007) Doma (2009) Hibernate 2 (2003)
  • 12. S2Daoから継承したこと 2 Way SQL 実装のいらないDAO
  • 13. S2Daoから継承しなかったこと 命名規約 SELECT文の自動生成 2 Way SQLの実装 /*BEGIN*/WHERE /*IF job != null*/job = /*job*/'CLERK'/*END*/ /*IF deptno != null*/AND deptno = /*deptno*/20/*END*/ /*END*/
  • 14. DBFluteから継承したこと DateFromTo: 時刻の切捨て/切上げ
  • 15. DBFluteから継承しなかったこと ReplaceSchemaなどの周辺ツール
  • 16. S2JDBCから継承したこと RDBMSの挙動の違いを抽象化する方法 自動生成系SQLの組み立て方
  • 17. S2JDBCから継承しなかったもの ライブラリへの依存 Criteria(流れるインタフェース)
  • 18. JPAから継承したもの アノテーション
  • 19. JPAから継承しなかったもの 永続コンテキスト リレーションシップ 遅延ローディング 専用の問い合わせ言語(JPQL)
  • 20. なぜ SQLテンプレート を使うべきか? 20
  • 21. 可読性を高くする • StringBuilderと条件分岐でクエリを組み立て るのは煩雑 StringBuilder buf = new StringBuilder(); buf.append("select * from emp"); if (id != null) { buf.append(" where id = ?"); } String sql = buf.toString(); select * from emp where /*%if e.id != null*/ id = /* e.id */0 /*%end */ ✖
  • 22. 検証しやすくする • StringBuilderで組み立てるとSQLの構文が正 しいか検証するのが手間 StringBuilder buf = new StringBuilder(); buf.append("select * from emp"); if (id != null) { buf.append("where id = ?"); } String sql = buf.toString(); select * from emp where /*%if e.id != null*/ id = /* e.id */0 /*%end */ ✖
  • 23. SQLインジェクションを防ぐ • 検索条件はPreparedStatementの?にバインド StringBuilder buf = new StringBuilder(); buf.append("select * from emp"); if (id != null) { buf.append(" where id = " + id); } String sql = buf.toString(); select * from employee where name = /* e.name */'hoge' select * from employee where name = ? ✖
  • 24. メンタルモデルに合わせる • SQLは専用のエディタでDBにつなぎ、小さく ちょっとずつ組み立てたい select * from emp select * from emp where salary > 1000 select * from emp where salary > 1000 order by name select name, salary from emp where salary > 1000 order by name select name, salary from emp where salary > /*e.salary*/0 order by name
  • 25. Domaの SQLテンプレートの 何が良いのか?
  • 26. 存在しないプロパティアクセ スはコンパイルエラー @Select List<Employee> selectByExample(Employee e); select * from emp where salary > /*e.hoge*/0
  • 27. 条件分岐の間違いはコンパイ ルエラー select * from emp where /*%if e.id != null */ id = /* id */0
  • 28. 広いスコープの条件分岐はコ ンパイルエラー /*%if e.name == null */ select count(*) from emp /*%else */ select * from emp where name = /* e.name */'hoge' /*%end * select * from emp where /*%if e.name == null */ name = /* e.name */'hoge' /*%else */ and name is null /*%end * ✖
  • 29. SQL構文木の構築と走査 29
  • 30. DAOインタフェース @Dao(config = AppConfig.class) public interface EmpDao { @Select Emp select(Emp e); @Select List<Emp> selectList(Emp e); }
  • 31. SQLテンプレートselect * from emp where パース 構文木 走査 /*%if e.id != null*/ id = /* e.id */0 /*%end */ マッピングや 式言語の文法 チェック • eはメソッドパラメータに存在する? • id はEmpに存在する? • if と end は対応している? コンパイル時
  • 32. SQLテンプレートselect * from emp where パース 構文木 実行時 走査 /*%if e.id != null*/ id = /* e.id */0 /*%end */ select * from emp where id = ? SQLの生成or select * from emp
  • 33. SQLテンプレートselect * from emp where パース 構文木 実行時(ページング) 変換 走査 salary > /* e.salary */0 ページング用 構文木 SQLの生成 select * from emp where salary > ? offset 10 limit 100
  • 34. パース 構文木 実行時(悲観的ロック) SQLテンプレートselect * from emp where id = /* e.id */0 変換 悲観的ロック用 構文木 SQLの生成 select * from emp where id = ? for update 走査
  • 35. なぜ構文木を構築する? SQLを変換したい コンパイル時と実行時で異なる処理をしたい が、できるだけ共通化したい
  • 36. RDBMSのSQL方言対応 パース時はRDBMSごとのSQL方言を考慮せ ず、共通的なノードのみ押さえる 変換(ページング、悲観的ロック)のみを方 言ごとに実行できるようにする 新しい方言への対応は容易な作り
  • 37. 構築と変換 データ構造
  • 38. SQLファイル select * from emp where /*%if e.id != null*/ id = /* e.id */0 /*%end */
  • 39. Anonymous SelectStatement SelectClause FromClause WhereClause Word Space Word Space from emp Word Space Other Space select * Word Space IfBlock where /*%if e.id != null */ If End /*%end */ Space Word Space Other Space BindVariable Space Word 0 id != /* e.id */ 木の構築
  • 40. Fragment offset 10 Fragment limit 100 If Anonymous SelectStatement SelectClause WhereClause IfBlock End Word Space Other FromClause Space Word Space Word Space Space select * from emp Space Word Space Other Space BindVariable Space id != /* e.id */ /*%end */ Word 0 /*%if e.id != null */ Word where 木の変換(ページング) OrderByClause
  • 41. If Anonymous SelectStatement SelectClause WhereClause IfBlock End Word Space Other FromClause Space Word Space Word Space Space select * from emp Space Word Space Other Space BindVariable Space id != /* e.id */ /*%end */ Word 0 /*%if e.id != null */ Word where 木の変換(悲観的ロック) ForUpdateClause Word for update
  • 42. スペースを保つ スタイルの維持 行や列数の報告
  • 43. 式言語の構築と走査 43
  • 44. Anonymous SelectStatement SelectClause FromClause WhereClause Word Space Word Space from emp Word Space Other Space select * Word Space IfBlock where /*%if e.id != null */ If End /*%end */ Space Word Space Other Space BindVariable Space Word 0 id != /* e.id */
  • 45. e.id != null NeOperator 木の構築 FieldOperator Literal id Variable null != e FieldOperator id Variable e e.id • コンパイル時にも実行時にも走査
  • 46. まとめ 46
  • 47. まとめ • DomaのSQLテンプレートはコンパイル時 チェックが可能 • SQLの構文木と式言語の構文木を構築して チェック • 新しいRDMBSへの対応は容易
  • 48. ハックして何か新しい機能を!
  • 49. 参考情報 49
  • 50. GitHub Repository https://github.com/domaframework/doma
  • 51. Doma 2 Java 8 時代のDBアクセス https://nakamura-to.github.io/presentation-doma2- with-java8/
  • 52. Thank you