SlideShare a Scribd company logo
Doma 
SQLテンプレートのしくみ 
by @nakamura_to
@nakamura_to
Domaとは ? 
3
DBアクセスライブラリ 
• コンパイル時のコード生成 & チェック 
• 2 Way SQL対応テンプレート 
• Java 8対応 
• 依存ライブラリなし
デモ 
5
DAOインタフェース 
example/EmployeeDao.java 
@Dao(config = AppConfig.class) 
public interface EmployeeDao { 
@Select 
Employee selectById(Integer id); 
}
SQLファイル 
META-INF/example/EmployeeDao/selectById.sql 
select 
* 
from 
employee 
where 
id = /* id */0
コンパイル 
• SQLファイルの存在チェック 
• バインド変数のマッピングチェック 
• DAO実装クラスの生成
実行 
EmployeeDao employeeDao = new EmployeeDaoImpl(); 
Employee result = employeeDao.selectById(1); 
select 
* 
from 
employee 
where 
id = ?
Domaの系譜 
10
S2Dao 
(2004) 
DBFlute 
(2006) 
JPA 
(2006) 
S2JDBC 
(2007) 
Doma 
(2009) 
Hibernate 2 
(2003)
S2Daoから継承したこと 
2 Way SQL 
実装のいらないDAO
S2Daoから継承しなかったこと 
命名規約 
SELECT文の自動生成 
2 Way SQLの実装 
/*BEGIN*/WHERE 
/*IF job != null*/job = /*job*/'CLERK'/*END*/ 
/*IF deptno != null*/AND deptno = /*deptno*/20/*END*/ 
/*END*/
DBFluteから継承したこと 
DateFromTo: 時刻の切捨て/切上げ
DBFluteから継承しなかったこと 
ReplaceSchemaなどの周辺ツール
S2JDBCから継承したこと 
RDBMSの挙動の違いを抽象化する方法 
自動生成系SQLの組み立て方
S2JDBCから継承しなかったもの 
ライブラリへの依存 
Criteria(流れるインタフェース)
JPAから継承したもの 
アノテーション
JPAから継承しなかったもの 
永続コンテキスト 
リレーションシップ 
遅延ローディング 
専用の問い合わせ言語(JPQL)
なぜ 
SQLテンプレート 
を使うべきか? 
20
可読性を高くする 
• 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 */ 
✖
検証しやすくする 
• 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 */ 
✖
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 = ? 
✖
メンタルモデルに合わせる 
• 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
Domaの 
SQLテンプレートの 
何が良いのか?
存在しないプロパティアクセ 
スはコンパイルエラー 
@Select 
List<Employee> selectByExample(Employee e); 
select * from emp where salary > /*e.hoge*/0
条件分岐の間違いはコンパイ 
ルエラー 
select * from emp where 
/*%if e.id != null */ 
id = /* id */0
広いスコープの条件分岐はコ 
ンパイルエラー 
/*%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 * 
✖
SQL構文木の構築と走査 
29
DAOインタフェース 
@Dao(config = AppConfig.class) 
public interface EmpDao { 
@Select 
Emp select(Emp e); 
@Select 
List<Emp> selectList(Emp e); 
}
SQLテンプレートselect * from emp where 
パース 
構文木 
走査 
/*%if e.id != null*/ 
id = /* e.id */0 
/*%end */ 
マッピングや 
式言語の文法 
チェック 
• eはメソッドパラメータに存在する? 
• id はEmpに存在する? 
• if と end は対応している? 
コンパイル時
SQLテンプレートselect * from emp where 
パース 
構文木 
実行時 
走査 
/*%if e.id != null*/ 
id = /* e.id */0 
/*%end */ 
select * from emp where 
id = ? 
SQLの生成or 
select * from emp
SQLテンプレートselect * from emp where 
パース 
構文木 
実行時(ページング) 
変換 
走査 
salary > /* e.salary */0 
ページング用 
構文木 
SQLの生成 
select * from emp where 
salary > ? 
offset 10 limit 100
パース 
構文木 
実行時(悲観的ロック) 
SQLテンプレートselect * from emp where 
id = /* e.id */0 
変換 
悲観的ロック用 
構文木 
SQLの生成 
select * from emp where 
id = ? 
for update 
走査
なぜ構文木を構築する? 
SQLを変換したい 
コンパイル時と実行時で異なる処理をしたい 
が、できるだけ共通化したい
RDBMSのSQL方言対応 
パース時はRDBMSごとのSQL方言を考慮せ 
ず、共通的なノードのみ押さえる 
変換(ページング、悲観的ロック)のみを方 
言ごとに実行できるようにする 
新しい方言への対応は容易な作り
構築と変換 
データ構造
SQLファイル 
select * from emp where 
/*%if e.id != null*/ 
id = /* e.id */0 
/*%end */
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 */ 
木の構築
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
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
スペースを保つ 
スタイルの維持 
行や列数の報告
式言語の構築と走査 
43
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 */
e.id != null 
NeOperator 
木の構築 
FieldOperator Literal 
id 
Variable 
null 
!= 
e 
FieldOperator 
id 
Variable 
e 
e.id 
• コンパイル時にも実行時にも走査
まとめ 
46
まとめ 
• DomaのSQLテンプレートはコンパイル時 
チェックが可能 
• SQLの構文木と式言語の構文木を構築して 
チェック 
• 新しいRDMBSへの対応は容易
ハックして何か新しい機能を!
参考情報 
49
GitHub Repository 
https://github.com/domaframework/doma
Doma 2 
Java 8 時代のDBアクセス 
https://nakamura-to.github.io/presentation-doma2- 
with-java8/
Thank you

More Related Content

PDF
怖くないSpring Bootのオートコンフィグレーション
PDF
これからSpringを使う開発者が知っておくべきこと
PDF
O/Rマッパーによるトラブルを未然に防ぐ
PDF
今さら聞けないDiとspring
PPTX
PDF
オブジェクト指向の設計と実装の学び方のコツ
PDF
イミュータブルデータモデルの極意
PDF
ドメイン駆動設計のための Spring の上手な使い方
怖くないSpring Bootのオートコンフィグレーション
これからSpringを使う開発者が知っておくべきこと
O/Rマッパーによるトラブルを未然に防ぐ
今さら聞けないDiとspring
オブジェクト指向の設計と実装の学び方のコツ
イミュータブルデータモデルの極意
ドメイン駆動設計のための Spring の上手な使い方

What's hot (20)

PDF
インメモリーデータグリッドの選択肢
PPTX
RLSを用いたマルチテナント実装 for Django
PDF
Spring bootでweb バリデート編
PDF
ドメイン駆動設計という仕事の流儀
PDF
Springを何となく使ってる人が抑えるべきポイント
PDF
規格書で読むC++11のスレッド
PDF
イミュータブルデータモデル(世代編)
PDF
ちいさなオブジェクトでドメインモデルを組み立てる
PDF
イミュータブルデータモデル(入門編)
PDF
ヤフー社内でやってるMySQLチューニングセミナー大公開
PDF
なぜデータモデリングが重要なのか?
PDF
並行処理初心者のためのAkka入門
PDF
emscriptenでC/C++プログラムをwebブラウザから使うまでの難所攻略
PPTX
さくっと理解するSpring bootの仕組み
PDF
入社1年目のプログラミング初心者がSpringを学ぶための手引き
PDF
C++でCプリプロセッサを作ったり速くしたりしたお話
PDF
Spring Bootをはじめる時にやるべき10のこと
PDF
できる!並列・並行プログラミング
PDF
ドメインオブジェクトの見つけ方・作り方・育て方
PDF
Where狙いのキー、order by狙いのキー
インメモリーデータグリッドの選択肢
RLSを用いたマルチテナント実装 for Django
Spring bootでweb バリデート編
ドメイン駆動設計という仕事の流儀
Springを何となく使ってる人が抑えるべきポイント
規格書で読むC++11のスレッド
イミュータブルデータモデル(世代編)
ちいさなオブジェクトでドメインモデルを組み立てる
イミュータブルデータモデル(入門編)
ヤフー社内でやってるMySQLチューニングセミナー大公開
なぜデータモデリングが重要なのか?
並行処理初心者のためのAkka入門
emscriptenでC/C++プログラムをwebブラウザから使うまでの難所攻略
さくっと理解するSpring bootの仕組み
入社1年目のプログラミング初心者がSpringを学ぶための手引き
C++でCプリプロセッサを作ったり速くしたりしたお話
Spring Bootをはじめる時にやるべき10のこと
できる!並列・並行プログラミング
ドメインオブジェクトの見つけ方・作り方・育て方
Where狙いのキー、order by狙いのキー
Ad

Similar to Doma SQLテンプレートのしくみ (20)

PPT
次世代DaoフレームワークDoma
PDF
20091030cakephphandson 02
PDF
「Html sql」で図書館hpにアクセスしてみよう
PDF
Kanazawa.js.Next
KEY
PDF
DeclarativeSql
PDF
eZ Publish勉強会9月〜テンプレート言語〜
PPT
S2dao Seminar in tripodworks
PDF
Perl勉強会#2資料
PPTX
PHP AST 徹底解説
PDF
知って得する標準関数の使い方
PDF
Reading Anorm 2.0
PDF
Groovyで楽にSQLを実行してみよう
PDF
よろしい、ならばMicro-ORMだ
PDF
Java による Web アプリケーションのプロトタイプのために最近使っている構成
PDF
第2回品川Redmine勉強会(日本語全文検索)
PDF
Java オブジェクトの内部構造
PPTX
final int をFINAL しやがれ!
PPTX
PPTX
URLで遊ぼう
次世代DaoフレームワークDoma
20091030cakephphandson 02
「Html sql」で図書館hpにアクセスしてみよう
Kanazawa.js.Next
DeclarativeSql
eZ Publish勉強会9月〜テンプレート言語〜
S2dao Seminar in tripodworks
Perl勉強会#2資料
PHP AST 徹底解説
知って得する標準関数の使い方
Reading Anorm 2.0
Groovyで楽にSQLを実行してみよう
よろしい、ならばMicro-ORMだ
Java による Web アプリケーションのプロトタイプのために最近使っている構成
第2回品川Redmine勉強会(日本語全文検索)
Java オブジェクトの内部構造
final int をFINAL しやがれ!
URLで遊ぼう
Ad

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