目次
検索を行うには、 @Select
をDaoのメソッドに注釈します。
@Config(config = AppConfig.class)
public interface EmployeeDao {
@Select
List<Employee> selectByDepartmentName(String departmentName);
...
}
検索では、 SQLファイルが必須 です。 検索系のSQLを自動生成する機能はありません。
Note
エンティティクラスを利用する場合、エンティティクラスは 検索結果に応じて 作成する必要があります。 たとえば、EMPLOYEEテーブルに対応するEmployeeエンティティクラスが定義されている場合、 EMPLOYEEテーブルのカラムを含む結果セットはEmployeeエンティティクラスで受けられますが、 EMPLOYEEテーブルとDEPARTMENTテーブルを結合して得られる結果セットに対しては、 Employeeエンティティクラスとは別のクラス(たとえばEmployeeDepartmentクラス)が必要です。
問い合わせ条件にはメソッドのパラメータを使用します。 利用できるパラメータの型は以下のものです。
../basic
../domain
- 任意の型
../basic
や../domain
や任意の型を要素とするjava.util.Optional../basic
や../domain
を要素とするjava.util.Iterable- java.util.OptionalInt
- java.util.OptionalLong
- java.util.OptionalDouble
パラメータの数に制限はありません。 パラメータの型が ../basic
もしくは ../domain
の場合、引数を null
にできます。 それ以外の型の場合、引数は null
であってはいけません。
メソッドやパラメータに ../basic
や ../domain
を定義します。
@Select
List<Employee> selectByNameAndSalary(String name, Salary salary);
SQLファイルではSQLコメントを使いメソッドのパラメータをSQLにマッピングさせます。 SQLコメントではメソッドのパラメータ名を参照します。
select * from employee where employee_name = /* name */'hoge' and salary > /* salary */100
メソッドのパラメータに任意の型を使用する場合は、ドット .
でフィールドにアクセスしたりメソッドを呼び出すなどしてSQLにマッピングさせます。
@Select
List<Employee> selectByExample(Employee employee);
select * from employee where employee_name = /* employee.name */'hoge' and salary > /* employee.getSalary() */100
パラメータは複数指定できます。
@Select
List<Employee> selectByEmployeeAndDepartment(Employee employee, Department department);
java.lang.Iterable
のサブタイプは、 IN句を利用した検索を行う場合に使用します。
@Select
List<Employee> selectByNames(List<String> names);
select * from employee where employee_name in /* names */('aaa','bbb','ccc')
1件を検索するには、メソッドの戻り値の型を次のいずれかにします。
../basic
../domain
../entity
- java.util.Map<String, Object>
../basic
、../domain
、../entity
、 java.util.Map<String, Object> のいずれかを要素とするjava.util.Optional- java.util.OptionalInt
- java.util.OptionalLong
- java.util.OptionalDouble
@Select
Employee selectByNameAndSalary(String name, BigDecimal salary);
戻り値の型が Optional
でなく、かつ、結果が0件のときは null
が返されます。 検索結果の保証 を有効にした場合は、戻り値の型に関係なく結果が0件ならば例外がスローされます。
結果が2件以上存在するときは、 NonUniqueResultException
がスローされます。
複数件を検索するには、メソッドの戻り値の型を java.util.List
にします。 List
の要素の型には次のものが使用できます。
../basic
../domain
../entity
- java.util.Map<String, Object>
../basic
もしくは../domain
のいずれかを要素とするjava.util.Optional- java.util.OptionalInt
- java.util.OptionalLong
- java.util.OptionalDouble
@Select
List<Employee> selectByNameAndSalary(String name, Salary salary);
結果が0件のときは null
ではなく空のListが返されます。 ただし、 検索結果の保証 を有効にした場合、結果が0件ならば例外がスローされます。
全件を一度に java.util.List
で受け取るのではなく java.util.stream.Stream
で扱いたい場合は、ストリーム検索を利用できます。
ストリーム検索を実施するには、 @Select
の strategy
要素に SelectType.STREAM
を設定し、 メソッドのパラメータに java.util.Function<Stream<TARGET>, RESULT>
もしくは java.util.Function<Stream<TARGET>, RESULT>
のサブタイプを定義します。
@Select(strategy = SelectType.STREAM)
BigDecimal selectByNameAndSalary(String name, BigDecimal salary, Function<Stream<Employee>, BigDecimal> mapper);
呼び出し元はストリームを受け取って結果を返すラムダ式を渡します。
EmployeeDao dao = new EmployeeDao();
BigDecimal result = dao.selectByNameAndSalary(name, salary, stream -> {
return ...;
});
Function<Stream<TARGET>, RESULT>
の型パラメータ TARGET
は次のいずれかでなければいけません。
../basic
../domain
../entity
- java.util.Map<String, Object>
../basic
もしくは../domain
のいずれかを要素とするjava.util.Optional- java.util.OptionalInt
- java.util.OptionalLong
- java.util.OptionalDouble
型パラメータ RESULT
はDaoのメソッドの戻り値に合わせなければいけません。
検索結果の保証 を有効にした場合、結果が0件ならば例外がスローされます。
検索結果を java.util.Collector
で処理したい場合は、コレクト検索を利用できます。
コレクト検索を実施するには、 @Select
の strategy
要素に SelectType.COLLECT
を設定し、 メソッドのパラメータに java.stream.Collector<TARGET, ACCUMULATION, RESULT>
もしくは java.stream.Collector<TARGET, ?, RESULT>
のサブタイプを定義します。
@Select(strategy = SelectType.COLLECT)
<RESULT> RESULT selectBySalary(BigDecimal salary, Collector<Employee, ?, RESULT> collector);
呼び出し元は Collector
のインスタンスを渡します。
EmployeeDao dao = new EmployeeDaoImpl();
Map<Integer, List<Employee>> result =
dao.selectBySalary(salary, Collectors.groupingBy(Employee::getDepartmentId));
Collector<TARGET, ACCUMULATION, RESULT>
の型パラメータ TARGET
は次のいずれかでなければいけません。
../basic
../domain
../entity
- java.util.Map<String, Object>
../basic
もしくは../domain
のいずれかを要素とするjava.util.Optional- java.util.OptionalInt
- java.util.OptionalLong
- java.util.OptionalDouble
型パラメータ RESULT
はDaoのメソッドの戻り値に合わせなければいけません。
検索結果の保証 を有効にした場合、結果が0件ならば例外がスローされます。
Note
コレクト検索はストリーム検索のショートカットです。 ストリーム検索で得られる Stream
オブジェクトの collect
メソッドを使って同等のことができます。
検索オプションを表す SelectOptions
を使用することで、SELECT文が記述されたSQLファイルをベースにし、 ページング処理や悲観的排他制御用のSQLを自動で生成できます。
SelectOptions
は、 1件検索 、 複数件検索 、 ストリーム検索 と組み合わせて使用します。
SelectOptions
は、Daoのメソッドのパラメータとして定義します。
@Config(config = AppConfig.class)
public interface EmployeeDao {
@Select
List<Employee> selectByDepartmentName(String departmentName, SelectOptions options);
...
}
SelectOptions
のインスタンスは、staticな get
メソッドにより取得できます。
SelectOptions options = SelectOptions.get();
SelectOptions
の offset
メソッドで開始位置、 limit
メソッドで取得件数を指定し、 SelectOptions
のインスタンスをDaoのメソッドに渡します。
SelectOptions options = SelectOptions.get().offset(5).limit(10);
EmployeeDao dao = new EmployeeDao();
List<Employee> list = dao.selectByDepartmentName("ACCOUNT", options);
ページングは、ファイルに記述されているオリジナルのSQLを書き換え実行することで実現されています。 オリジナルのSQLは次の条件を満たしていなければいけません。
- SELECT文である
- 最上位のレベルでUNION、EXCEPT、INTERSECT等の集合演算を行っていない(サブクエリで利用している場合は可)
- ページング処理を含んでいない
さらに、データベースの方言によっては特定の条件を満たしていなければいけません。
Dialect | 条件 |
---|---|
Db2Dialect |
|
Mssql2008Dialect |
|
StandardDialect |
|
SelectOptions
の forUpdate
メソッドで悲観的排他制御を行うことを示し、 SelectOptionsのインスタンスをDaoのメソッドに渡します。
SelectOptions options = SelectOptions.get().forUpdate();
EmployeeDao dao = new EmployeeDao();
List<Employee> list = dao.selectByDepartmentName("ACCOUNT", options);
SelectOptions
には、ロック対象のテーブルやカラムのエイリアスを指定できる forUpdate
メソッドや、 ロックの取得を待機しない forUpdateNowait
など、名前が forUpdate で始まる悲観的排他制御用のメソッドが用意されています。
悲観的排他制御は、ファイルに記述されているオリジナルのSQLを書き換えて実行しています。 オリジナルのSQLは次の条件を満たしていなければいけません。
- SELECT文である
- 最上位のレベルでUNION、EXCEPT、INTERSECT等の集合演算を行っていない(サブクエリで利用している場合は可)
- 悲観的排他制御の処理を含んでいない
データベースの方言によっては、悲観的排他制御用のメソッドのすべてもしくは一部が使用できません。
Dialect | 説明 |
---|---|
Db2Dialect |
|
H2Dialect |
|
HsqldbDialect |
|
Mssql2008Dialect |
|
MysqlDialect |
|
OracleDialect |
|
PostgresDialect |
|
StandardDialect |
|
SelectOptions
の count
メソッドを呼び出すことで集計件数を取得できるようになります。 通常、ページングのオプションと組み合わせて使用し、ページングで絞り込まない場合の全件数を取得する場合に使います。
SelectOptions options = SelectOptions.get().offset(5).limit(10).count();
EmployeeDao dao = new EmployeeDao();
List<Employee> list = dao.selectByDepartmentName("ACCOUNT", options);
long count = options.getCount();
集計件数は、Daoのメソッド呼出し後に SelectOptions
の getCount
メソッドを使って取得します。 メソッド呼び出しの前に count
メソッドを実行していない場合、 getCount
メソッドは -
1を返します。
検索結果が1件以上存在することを保証したい場合は、 @Select
の ensureResult
要素に true
を指定します。
@Select(ensureResult = true)
Employee selectById(Integer id);
検索結果が0件ならば NoResultException
がスローされます。
エンティティのプロパティすべてに対して漏れなく結果セットのカラムをマッピングすることを保証したい場合は、 @Select
の ensureResultMapping
要素に true
を指定します。
@Select(ensureResultMapping = true)
Employee selectById(Integer id);
結果セットのカラムにマッピングされないプロパティが存在する場合 ResultMappingException
がスローされます。
@Select
の queryTimeout
要素にクエリタイムアウトの秒数を指定できます。
@Select(queryTimeout = 10)
List<Employee> selectAll();
値を指定しない場合、 ../config
に指定されたクエリタイムアウトが使用されます。
@Select
の fetchSize
要素にフェッチサイズを指定できます。
@Select(fetchSize = 20) List<Employee> selectAll();
値を指定しない場合、 ../config
に指定されたフェッチサイズが使用されます。
@Select
の maxRows
要素に最大行数を指定できます。
@Select(maxRows = 100)
List<Employee> selectAll();
値を指定しない場合、 ../config
に指定された最大行数が使用されます。
検索結果を java.util.Map<String, Object>
にマッピングする場合、 @Select
の mapKeyNaming
要素にマップのキーのネーミング規約を指定できます。
@Select(mapKeyNaming = MapKeyNamingType.CAMEL_CASE)
List<Map<String, Object>> selectAll();
MapKeyNamingType.CAMEL_CASE
は、カラム名をキャメルケースに変換することを示します。 そのほかにカラム名を大文字や小文字に変換する規約があります。
最終的な変換結果は、ここに指定した値と ../config
に指定された MapKeyNaming
の実装により決まります。
@Select
の sqlLog
要素に SQL のログ出力形式を指定できます。
@Select(sqlLog = SqlLogType.RAW)
List<Employee> selectById(Integer id);
SqlLogType.RAW
はバインドパラメータ(?)付きの SQL をログ出力することを表します。