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
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 *
✖
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
走査
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
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
• コンパイル時にも実行時にも走査