概要
検索は、すべて外部化されたSQLを使って行われます。
外部化されたSQLはすべてバインド変数(?)を使った準備された文に変換されて実行されますが、 このドキュメントでは、発行されたSQLがどのようなものかわかりやすくするためにバインド変数を実際の値に置き換えたログ用のSQLを示します。
単純な検索
test/tutorial/SelectTest.javaのtestSimpleSelectメソッドを参照してください。 引数をSQLファイルにバインディングして実行する単純な検索です。
使用するDaoのメソッド定義は次のとおりです。
@Select Employee selectById(Integer id);
Daoメソッドに対応するSQLファイルのパスはMETA-INF/tutorial/dao/EmployeeDao/selectById.sqlです。SQLは次のように記述されています。
select * from employee where id = /* id */0
Daoのメソッドは次のように呼び出します。
Employee employee = dao.selectById(1);
SQLのログは次のように出力されます。
select * from employee where id = 1
条件分岐を用いた検索
test/tutorial/SelectTest.javaのtestConditinalSelectメソッドを参照してください。 SQLファイル中に条件分岐を記述することで、動的なSQLを発行できます。
使用するDaoのメソッド定義は次のとおりです。
@Select List<Employee> selectByAgeRange(Integer min, Integer max);
Daoメソッドに対応するSQLファイルのパスはMETA-INF/tutorial/dao/EmployeeDao/selectByAgeRange.sqlです。SQLは次のように記述されています。
select * from employee where /*%if min != null */ age >= /* min */10 /*%end */ /*%if max != null */ and age <= /* max */70 /*%end */ order by age
条件1
1番目のパラメータに30、2番目のパラメータに40を渡してDaoのメソッドを呼び出します。
List<Employee> list = dao.selectByAgeRange(30, 40);
SQLのログは次のように出力されます。
select * from employee where age >= 30 and age <= 40 order by age
条件2
1番目のパラメータに30、2番目のパラメータにnullを渡してDaoのメソッドを呼び出します。
list = dao.selectByAgeRange(30, null);
SQLのログは次のように出力されます。
select * from employee where age >= 30 order by age
繰り返しを用いた検索
test/tutorial/SelectTest.javaのtestLoopSelectメソッドを参照してください。 SQLファイル中に繰り返しを記述することで、動的なSQLを発行できます。
使用するDaoのメソッド定義は次のとおりです。
@Select List<Employee> selectByAges(List<Integer> ages);
Daoメソッドに対応するSQLファイルのパスはMETA-INF/tutorial/dao/EmployeeDao/selectByAges.sqlです。SQLは次のように記述されています。
select * from employee where /*%for age : ages */ age = /* age */30 /*%if age_has_next */ or /*%end */ /*%end */
Daoのメソッドは次のように呼び出します。
List<Integer> ages = Arrays.asList(30, 40, 50, 60); List<Employee> list = dao.selectByAges(ages);
SQLのログは次のように出力されます。
select * from employee where age = 30 or age = 40 or age = 50 or age = 60;
IN述語による検索
test/tutorial/SelectTest.javaのtestInPredicateメソッドを参照してください。 IN述語を使った検索です。
使用するDaoのメソッド定義は次のとおりです。
@Select List<Employee> selectByNames(List<String> names);
Daoメソッドに対応するSQLファイルのパスはMETA-INF/tutorial/dao/EmployeeDao/selectByNames.sqlです。SQLは次のように記述されています。
select * from employee where name in /* names */('aaa', 'bbb')'
Daoのメソッドは次のように呼び出します。
List<String> names = Arrays.asList("JONES", "SCOTT", "XXX"); List<Employee> list = dao.selectByNames(names);
SQLのログは次のように出力されます。
select * from employee where name in ('JONES', 'SCOTT', 'XXX')
LIKE述語による検索
前方一致検索
test/tutorial/SelectTest.javaのtestLikePredicate_prefixメソッドを参照してください。 SQLファイル中で組み込み関数「@prefix()」を使用した前方一致検索ができます。 組み込み関数「@prefix()」を使用するとJavaのコード内で「%」を文字列に連結する処理が不要になります。
使用するDaoのメソッド定義は次のとおりです。
@Select List<Employee> selectByNameWithPrefixMatching(String prefix);
Daoメソッドに対応するSQLファイルのパスはMETA-INF/tutorial/dao/EmployeeDao/selectByNameWithPrefixMatching.sqlです。SQLは次のように記述されています。
select * from employee where name like /* @prefix(prefix) */'X%'
Daoのメソッドは次のように呼び出します。
List<Employee> list = dao.selectByNameWithPrefixMatching("S");
SQLのログは次のように出力されます。
select * from employee where name like 'S%'
後方一致検索
test/tutorial/SelectTest.javaのtestLikePredicate_suffixメソッドを参照してください。 SQLファイル中で組み込み関数「@suffix()」を使用した後方一致検索ができます。 組み込み関数「@suffix()」を使用するとJavaのコード内で「%」を文字列に連結する処理が不要になります。
使用するDaoのメソッド定義は次のとおりです。
@Select List<Employee> selectByNameWithSuffixMatching(String suffix);
Daoメソッドに対応するSQLファイルのパスはMETA-INF/tutorial/dao/EmployeeDao/selectByNameWithSuffixMatching.sqlです。SQLは次のように記述されています。
select * from employee where name like /* @suffix(suffix) */'%X'
Daoのメソッドは次のように呼び出します。
List<Employee> list = dao.selectByNameWithSuffixMatching("S");
SQLのログは次のように出力されます。
select * from employee where name like '%S'
中間一致検索
test/tutorial/SelectTest.javaのtestLikePredicate_insideメソッドを参照してください。 SQLファイル中で組み込み関数「@contain()」を使用した中間一致検索ができます。 組み込み関数「@contain()」を使用するとJavaのコード内で「%」を文字列に連結する処理が不要になります。
使用するDaoのメソッド定義は次のとおりです。
@Select List<Employee> selectByNameWithInsideMatching(String inside);
Daoメソッドに対応するSQLファイルのパスはMETA-INF/tutorial/dao/EmployeeDao/selectByNameWithInsideMatching.sqlです。SQLは次のように記述されています。
select * from employee where name like /* @contain(inside) */'%X%'
Daoのメソッドは次のように呼び出します。
List<Employee> list = dao.selectByNameWithInsideMatching("A");
SQLのログは次のように出力されます。
select * from employee where name like '%A%'
日付による範囲検索
test/tutorial/SelectTest.javaのtestSelectByTimestampRangeメソッドを参照してください。 日付を用いて範囲検索を行う場合に、日付の時刻部分を切り捨てたり、日付を一日後ろへずらして切りのいい値にしたいことがあります。 そのような場合には、組み込み関数の「@roundDownTimePart()」と「@roundUpTimePart()」を使用します。
使用するDaoのメソッド定義は次のとおりです。
@Select List<Employee> selectByHiredateRange(Timestamp from, Timestamp to);
Daoメソッドに対応するSQLファイルのパスはMETA-INF/tutorial/dao/EmployeeDao/selectByHiredateRange.sqlです。SQLは次のように記述されています。
select * from employee where hiredate >= /* @roundDownTimePart(from) */'2001-01-01 12:34:56' and hiredate < /* @roundUpTimePart(to) */'2001-01-01 12:34:56'
Daoのメソッドは次のように呼び出します。
Timestamp from = Timestamp.valueOf("2008-01-20 12:34:56"); Timestamp to = Timestamp.valueOf("2008-03-20 12:34:56"); List<Employee> list = dao.selectByHiredateRange(from, to);
SQLのログは次のように出力されます。
select * from employee where hiredate >= '2008-01-20 00:00:00.0' and hiredate < '2008-03-21 00:00:00.0'
Javaコードからの引数と比べると時刻部分の切り捨てや切り上げが行われていることがわかります。
ドメインによる検索
test/tutorial/SelectTest.javaのtestSelectByDomainメソッドを参照してください。 ドメインを条件に使用した検索です。
使用するDaoのメソッド定義は次のとおりです。
@Select List<Employee> selectBySalary(Salary salary);
Daoメソッドに対応するSQLファイルのパスはMETA-INF/tutorial/dao/EmployeeDao/selectBySalary.sqlです。 SQLは次のように記述されています。 パラメータの型がドメインクラスであっても、SQLファイルでの扱い方は基本型と変わりません。
select * from employee where salary > /* salary */0
Daoのメソッドは次のように呼び出します。
List<Employee> list = dao.selectBySalary(new Salary(2900));
SQLのログは次のように出力されます。
select * from employee where salary > 2900
エンティティによる検索
test/tutorial/SelectTest.javaのtestSelectByEntityメソッドを参照してください。 エンティティを条件に使用した検索です。
使用するDaoのメソッド定義は次のとおりです。
@Select List<Employee> selectByExample(Employee e);
Daoメソッドに対応するSQLファイルのパスはMETA-INF/tutorial/dao/EmployeeDao/selectByExample.sqlです。 SQLは次のように記述されています。 パラメータの型がエンティティクラスの場合、SQLファイルの中ではドットを使用してエンティティのプロパティにアクセスできます。
select * from employee where name = /* e.name */'aaa'
Daoのメソッドは次のように呼び出します。
Employee e = new Employee(); e.setName("SMITH"); List<Employee> list = dao.selectByExample(e);
SQLのログは次のように出力されます。
select * from employee where name = 'SMITH'
ページングを行う検索
test/tutorial/SelectTest.javaのtestOffsetLimitメソッドを参照してください。 ページングを行う検索です。
使用するDaoのメソッド定義は次のとおりです。 Daoのメソッドでは、SelectOptions型のパラメータを定義します。
@Select List<Employee> selectAll(SelectOptions options);
Daoメソッドに対応するSQLファイルのパスはMETA-INF/tutorial/dao/EmployeeDao/selectAll.sqlです。 SQLは次のように記述されています。 SQLにはORDER BY句の存在が必須です。
select * from employee order by id
Daoのメソッドは次のように呼び出します。 SelectOptionsにoffsetとlimitを指定しています。
SelectOptions options = SelectOptions.get().offset(5).limit(3); List<Employee> list = dao.selectAll(options); assertEquals(3, list.size());
SQLのログは次のように出力されます。
select * from employee order by id limit 3 offset 5
ページングと集計を同時に行う検索
test/tutorial/SelectTest.javaのtestCountメソッドを参照してください。 ページングと集計(ページングしない場合の全件数の取得)を同時に行う検索です。
使用するDaoのメソッド定義は次のとおりです。 Daoのメソッドでは、SelectOptions型のパラメータを定義します。
@Select List<Employee> selectAll(SelectOptions options);
Daoメソッドに対応するSQLファイルのパスはMETA-INF/tutorial/dao/EmployeeDao/selectAll.sqlです。 SQLは次のように記述されています。 SQLにはORDER BY句の存在が必須です。
select * from employee order by id
Daoのメソッドは次のように呼び出します。 SelectOptionsのcountメソッドをあらかじめ呼び出しておきます。 Daoのメソッドを呼び出した後、SelectOptionsのgetCountメソッドにより集計結果を取得できます。
SelectOptions options = SelectOptions.get().offset(5).limit(3).count(); List<Employee> list = dao.selectAll(options); assertEquals(3, list.size()); assertEquals(14, options.getCount());
SQLのログは次のように2つ出力されます。
select * from employee order by id limit 3 offset 5
select count(*) from ( select * from employee ) t_
イテレーション検索
test/tutorial/SelectTest.javaのtestIterateメソッドを参照してください。 SQLの結果セットを1件ずつエンティティなどのオブジェクトへインスタンス化する検索です。 メモリの使用量を抑えながら大量データを扱う場合に向いています。
使用するDaoのメソッド定義は次のとおりです。 @Selectのiterate要素にtrueを指定し、DaoのメソッドではIterationCallback型のパラメータを定義します。
@Select(iterate = true) <R> R selectByAge(int age, IterationCallback<R, Employee> callback);
Daoメソッドに対応するSQLファイルのパスはMETA-INF/tutorial/dao/EmployeeDao/selectByAge.sqlです。 SQLは次のように記述されています。
select * from employee where age > /* age */0 order by age
Daoのメソッドは次のように呼び出します。
Salary sum = dao.selectByAge(30, new IterationCallback<Salary, Employee>() { private Salary sum = new Salary(0); @Override public Salary iterate(Employee target, IterationContext context) { Salary salary = target.getSalary(); if (salary != null) { sum = sum.add(salary); } return sum; } });
SQLのログは次のように出力されます。
select * from employee where age > 30 order by age