<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
	<properties>
		<title>検索</title>
	</properties>
	<body>
		<section name="目次">
			<ul>
				<li><a href="#概要">概要</a></li>
				<li><a href="#問い合わせ条件">問い合わせ条件</a></li>
				<li><a href="#複数件検索">複数件検索</a></li>
				<li><a href="#1件検索">1件検索</a></li>
				<li><a href="#イテレーションによる検索">イテレーションによる検索</a></li>
				<li><a href="#検索オプションを利用した検索">検索オプションを利用した検索</a>
					<ul>
						<li><a href="#ページング">ページング</a></li>
						<li><a href="#悲観的排他制御">悲観的排他制御</a></li>
						<li><a href="#集計">集計</a></li>
					</ul>
				</li>
				<li><a href="#検索結果の保証">検索結果の保証</a></li>
				<li><a href="#検索結果のマッピングの保証">検索結果のマッピングの保証</a></li>
				<li><a href="#クエリタイムアウト">クエリタイムアウト</a></li>
				<li><a href="#フェッチサイズ">フェッチサイズ</a></li>
				<li><a href="#最大行数">最大行数</a></li>
				<li><a href="#マップのキーのネーミング規約">マップのキーのネーミング規約</a></li>
			</ul>
		</section>
		<section name="概要">
			<p>
				検索を行うには、 <a href="../../apidocs/org/seasar/doma/Select.html"><code>@Select</code></a>をDaoのメソッドに注釈します。
			</p>
<source><![CDATA[@Config(config = AppConfig.class)
public interface EmployeeDao {
    @Select
    List<Employee> selectByDepartmentName(String departmentName);
    ...
}]]></source>
			<p>
				検索では、<a href="../sqlfile.html">SQLファイル</a>が必須です。
				検索系のSQLを自動生成する機能はありません。
			</p>
			<p>
				検索結果を受ける型には、基本型、ドメインクラス、エンティティクラス、<code><![CDATA[java.util.Map<String, Object>]]></code>、また、それらを要素とする<code>java.util.List</code>を使用できますが、
				エンティティクラスを利用する場合、エンティティクラスは検索結果に応じて作成する必要があります。
			</p>
			<p>
				たとえば、EMPLOYEEテーブルに対応するEmployeeエンティティクラスが定義されている場合、
				EMPLOYEEテーブルのカラムを含む結果セットはEmployeeエンティティクラスで受けられますが、
				EMPLOYEEテーブルとDEPARTMENTテーブルを結合して得られる結果セットに対しては、Employeeエンティティクラスとは別のクラス（たとえばEmployeeDepartmentクラス）が必要です。
				通常は、テーブルごとにエンティティクラスを作成し、結合して得られる結果セットに対しては、テーブルに対応するエンティティクラスを継承したクラスを作成するのがよいでしょう。
				もちろん、継承せずに作成することも可能です。
			</p>
		</section>
		<section name="問い合わせ条件">
			<p>
				問い合わせ条件にはメソッドのパラメータを使用します。
				パラメータの型には、<a href="../basic.html">基本型</a>、<a href="../domain.html">ドメインクラス</a>、任意の型、
				および<a href="../basic.html">基本型</a>や<a href="../domain.html">ドメインクラス</a>を要素とする<code>java.lang.Iterable</code>のサブタイプが使用できます。
				パラメータの数に制限はありません。
				パラメータの型が基本型もしくはドメインクラスの場合、引数を<code>null</code>にできます。
				それ以外の型の場合、引数は<code>null</code>であってはいけません。
			</p>
<source><![CDATA[@Select
List<Employee> selectByNameAndSalary(String name, BigDecimal salary);]]></source>
			<p>
				<a href="../sqlfile.html">SQLファイル</a>ではSQLコメントを使いメソッドのパラメータをSQLにマッピングさせます。
				SQLコメントではメソッドのパラメータ名を参照します。
			</p>
<source><![CDATA[select * from employee where employee_name = /* name */'hoge' and salary > /* salary */100]]></source>
			<p>
				メソッドのパラメータに任意の型を使用する場合は、ドット（.）でフィールドにアクセスしたりメソッドを呼び出すなどしてSQLにマッピングさせます。
			</p>
<source><![CDATA[@Select
List<Employee> selectByExample(Employee employee);]]></source>
<source><![CDATA[select * from employee where employee_name = /* employee.name */'hoge' and salary > /* employee.getSalary() */100]]></source>
			<p>
				任意の型であっても複数のパラメータを指定できます。
			</p>
<source><![CDATA[@Select
List<Employee> selectByEmployeeAndDepartment(Employee employee, Department department);]]></source>
			<p>
				<a href="../basic.html">基本型</a>や<a href="../domain.html">ドメインクラス</a>を要素とする<code>java.lang.Iterable</code>のサブタイプは、
				IN句を利用した検索を行う場合に使用します。<code>java.lang.Iterable</code>のサブタイプは、通常<code>java.util.List</code>が適切でしょう。
			</p>
<source><![CDATA[@Select
List<Employee> selectByNames(List<String> names);]]></source>
<source><![CDATA[select * from employee where employee_name in /* names */('aaa','bbb','ccc')]]></source>
		</section>
		<section name="複数件検索">
			<p>
				複数件を検索するには、メソッドの戻り値の型を<code>java.util.List</code>にします。
				<code>List</code>の要素の型には、<a href="../basic.html">基本型</a>、<a href="../domain.html">ドメインクラス</a>、<a href="../entity.html">エンティティクラス</a>、<code><![CDATA[java.util.Map<String, Object>]]></code>が使用できます。
			</p>
<source><![CDATA[@Select
List<Employee> selectByNameAndSalary(String name, BigDecimal salary);]]></source>
			<p>
				結果が0件のときは、空の<code>List</code>が返されます。<code>null</code>は返されません。
				ただし、@Selectの<code>ensureResult</code>要素に<code>true</code>を指定した場合、
				結果が0件ならば<code>org.seasar.doma.jdbc.NoResultException</code>がスローされます。
			</p>
		</section>
		<section name="1件検索">
			<p>
				1件を検索するには、メソッドの戻り値の型を<a href="../basic.html">基本型</a>、<a href="../domain.html">ドメインクラス</a>、<a href="../entity.html">エンティティクラス</a>、<code><![CDATA[java.util.Map<String, Object>]]></code>のいずれかにします。
			</p>
<source><![CDATA[@Select
Employee selectByNameAndSalary(String name, BigDecimal salary);]]></source>
			<p>
				結果が0件のときは、<code>null</code>が返されます。
				ただし、@Selectの<code>ensureResult</code>要素に<code>true</code>を指定した場合、
				結果が0件ならば<code>org.seasar.doma.jdbc.NoResultException</code>がスローされます。
			</p>
			<p>
				結果が2件以上存在するときは、<code>org.seasar.doma.jdbc.NonUniqueResultException</code>がスローされます。
			</p>
		</section>
		<section name="イテレーションによる検索">
			<p>
				全件を一度に<code>List</code>で受け取るのではなく1件ずつ処理を行いたい場合は、
				イテレーションによる検索ができます。
				イテレーションによる検索を行うには、<code>@Select</code>の<code>iterate</code>要素を<code>true</code>に設定し、
				メソッドのパラメータに<code><![CDATA[org.seasar.doma.IterationCallback<R, T>]]></code>もしくは、
				<code><![CDATA[org.seasar.doma.IterationCallback<R, T>]]></code>のサブタイプを定義します。
			</p>
<source><![CDATA[@Select(iterate = true)
Void selectByNameAndSalary(String name, BigDecimal salary, IterationCallback<Void, Employee> callback);]]></source>
			<p>
				<code><![CDATA[IterationCallback]]></code>の<code>iterate</code>メソッドに検索対象がインスタンス化され1件ずつ渡されます。
			</p>
<source><![CDATA[EmployeeDao dao = new EmployeeDao();
dao.selectByNameAndSalary(name, salary, new IterationCallback<Void, Employee>() {
        @Override
        public Void iterate(Employee target, IterationContext context) {
            ...
            return null;
        }
    });]]></source>
			<p>
				<code><![CDATA[org.seasar.doma.IterationCallback<R, T>]]></code>の最初の型パラメータは、
				Daoのメソッドの戻り値にあわせなければいけません。2番目の型パラメータは、<a href="../basic.html">基本型</a>、<a href="../domain.html">ドメインクラス</a>、
				<a href="../entity.html">エンティティクラス</a>、<code><![CDATA[java.util.Map<String, Object>]]></code>のいずれかでなければいけません。
			</p>
			<p>
				@Selectの<code>ensureResult</code>要素に<code>true</code>を指定した場合、
				結果が0件ならば<code>org.seasar.doma.jdbc.NoResultException</code>がスローされます。
			</p>
			<p>
				イテレーションが完了した後に任意の処理を行うには、<code><![CDATA[org.seasar.doma.IterationCallback<R, T>]]></code>の代わりに
				<code><![CDATA[org.seasar.doma.PostIterationCallback<R, T>]]></code>のサブタイプを定義します。
				イテレーション完了後に<code>postIterate</code>が呼び出されます。
			</p>
<source><![CDATA[EmployeeDao dao = new EmployeeDao();
dao.selectByNameAndSalary(name, salary, new PostIterationCallback<Void, Employee>() {
        @Override
        public Void iterate(Employee target, IterationContext context) {
            ...
            return null;
        }

        @Override
        public Void postIterate(Void result, IterationContext context) {
            ...
            return null;
        }
    });]]></source>
		</section>
		<section name="検索オプションを利用した検索">
			<p>
				検索オプションのクラス<code>SelectOptions</code>を使用することで、SELECT文が記述されたSQLファイルをベースにし、
				ページング処理や悲観的排他制御用のSQLを自動で生成できます。
			</p>
			<p>
				<code>SelectOptions</code>は、<a href="#複数件検索">複数件検索</a>、
				<a href="#1件検索">1件検索</a>、<a href="#イテレーションによる検索">イテレーションによる検索</a>と組み合わせて使用します。
			</p>
			<p>
				<code>SelectOptions</code>は、Daoのメソッドのパラメータとして定義します。
			</p>
<source><![CDATA[@Config(config = AppConfig.class)
public interface EmployeeDao {
    @Select
    List<Employee> selectByDepartmentName(String departmentName, SelectOptions options);
    ...
}]]></source>
			<p>
				<code>SelectOptions</code>は、<code>SelectOptions</code>のstaticな<code>get</code>メソッドにより取得できます。
			</p>
<source><![CDATA[SelectOptions options = SelectOptions.get();]]></source>
			<subsection name="ページング">
				<p>
					<code>SelectOptions</code>の<code>offset</code>メソッドで開始位置、<code>limit</code>メソッドで取得件数を指定し、
					<code>SelectOptions</code>のインスタンスをDaoのメソッドに渡します。
				</p>
<source><![CDATA[SelectOptions options = SelectOptions.get().offset(5).limit(10);
EmployeeDao dao = new EmployeeDao();
List<Employee> list = dao.selectByDepartmentName("ACCOUNT", options);]]></source>
				<h4>ページングの制約</h4>
				<p>
					ページングは、ファイルに記述されているオリジナルのSQLを書き換え実行することで実現されています。
					オリジナルのSQLは次の条件を満たしていなければいけません。
				</p>
				<ul>
					<li>SELECT文である</li>
					<li>最上位のレベルでUNION、EXCEPT、INTERSECT等の集合演算を行っていない（サブクエリで利用している場合は可）</li>
					<li>ページング処理を含んでいない</li>
				</ul>
				<p>
					さらに、データベースの方言によっては特定の条件を満たしていなければいけません。
				</p>
				<table border="1" cellpadding="2" cellspacing="0">
					<tr><th>方言クラス</th><th>条件</th></tr>
					<tr><td><code>org.seasar.doma.jdbc.dialect.Db2Dialect</code></td><td>offsetを指定する場合、ORDER BY句を持ちORDER BY句で指定するカラムすべてをSELECT句に含んでいる。</td></tr>
					<tr><td><code>org.seasar.doma.jdbc.dialect.Mssql2008Dialect</code></td><td>offsetを指定する場合、ORDER BY句を持ちORDER BY句で指定するカラムすべてをSELECT句に含んでいる。</td></tr>
					<tr><td><code>org.seasar.doma.jdbc.dialect.StandardDialect</code></td><td>ORDER BY句を持ちORDER BY句で指定するカラムすべてをSELECT句に含んでいる。</td></tr>
				</table>
			</subsection>
			<subsection name="悲観的排他制御">
				<p>
					<code>SelectOptions</code>の<code>forUpdate</code>メソッドで悲観的排他制御を行うことを指示し、
					<code>SelectOptions</code>のインスタンスをDaoのメソッドに渡します。
				</p>
<source><![CDATA[SelectOptions options = SelectOptions.get().forUpdate();
EmployeeDao dao = new EmployeeDao();
List<Employee> list = dao.selectByDepartmentName("ACCOUNT", options);]]></source>
				<p>
					<code>SelectOptions</code>には、ロック対象のテーブルやカラムのエイリアスを指定できる<code>forUpdate</code>メソッドや、
					ロックの取得を待機しない<code>forUpdateNowait</code>など、名前が「forUpdate」で始まる悲観的排他制御用のメソッドが用意されています。
					詳しくは<a href="../../apidocs/org/seasar/doma/jdbc/SelectOptions.html">Javadocコメント</a>を参照ください。
				</p>
				<h4>悲観的排他制御の制約</h4>
				<p>
					悲観的排他制御は、ファイルに記述されているオリジナルのSQLを書き換え実行することで実現されています。
					オリジナルのSQLは次の条件を満たしていなければいけません。
				</p>
				<ul>
					<li>SELECT文である</li>
					<li>最上位のレベルでUNION、EXCEPT、INTERSECT等の集合演算を行っていない（サブクエリで利用している場合は可）</li>
					<li>悲観的排他制御の処理を含んでいない</li>
				</ul>
				<p>
					データベースの方言によっては、悲観的排他制御用のメソッドのすべてもしくは一部が使用できません。
				</p>
				<table border="1" cellpadding="2" cellspacing="0">
					<tr><th>方言クラス</th><th>説明</th></tr>
					<tr><td><code>org.seasar.doma.jdbc.dialect.Db2Dialect</code></td><td><code>forUpdate()</code>を使用できる。</td></tr>
					<tr><td><code>org.seasar.doma.jdbc.dialect.H2Dialect</code></td><td><code>forUpdate()</code>を使用できる。</td></tr>
					<tr><td><code>org.seasar.doma.jdbc.dialect.HsqldbDialect</code></td><td><code>forUpdate()</code>を使用できる。</td></tr>
					<tr><td><code>org.seasar.doma.jdbc.dialect.Mssql2008Dialect</code></td><td><code>forUpdate()</code>と<code>forUpdateNoWait()</code>を使用できる。ただし、オリジナルのSQLのFROM句は1つのテーブルだけから成らねばならない。</td></tr>
					<tr><td><code>org.seasar.doma.jdbc.dialect.MysqlDialect</code></td><td><code>forUpdate()</code>を使用できる。</td></tr>
					<tr><td><code>org.seasar.doma.jdbc.dialect.OracleDialect</code></td><td><code>forUpdate()</code>、<code>forUpdate(String... aliases)</code>、<code>forUpdateNowait()</code>、<code>forUpdateNowait(String... aliases)</code>、<code>	forUpdateWait(int waitSeconds)</code>、<code>forUpdateWait(int waitSeconds, String... aliases)</code>を使用できる。</td></tr>
					<tr><td><code>org.seasar.doma.jdbc.dialect.PostgresDialect</code></td><td><code>forUpdate()</code>と<code>forUpdate(String... aliases)</code>を使用できる。</td></tr>
					<tr><td><code>org.seasar.doma.jdbc.dialect.StandardDialect</code></td><td>悲観的排他制御用のメソッドすべてを使用できない。</td></tr>
				</table>
			</subsection>
			<subsection name="集計">
				<p>
					<code>SelectOptions</code>の<code>count</code>メソッドを呼び出すことで、集計件数を取得できるようになります。
					通常、ページングのオプションと組み合わせて使用し、ページングで絞り込まない場合の全件数を取得する場合に使います。
				</p>
<source><![CDATA[SelectOptions options = SelectOptions.get().offset(5).limit(10).count();
EmployeeDao dao = new EmployeeDao();
List<Employee> list = dao.selectByDepartmentName("ACCOUNT", options);
long count = options.getCount();]]></source>
				<p>
					集計件数は、Daoのメソッド呼出し後に、<code>SelectOptions</code>の<code>getCount</code>メソッドを使って取得します。
					メソッド呼び出しの前に<code>count</code>メソッドを実行していない場合、<code>getCount</code>メソッドは<code>-1</code>を返します。
				</p>
			</subsection>
		</section>
		<section name="検索結果の保証">
			<p>
				検索結果が1件以上存在することを保証したい場合は、<code>@Select</code>の<code>ensureResult</code>要素に<code>true</code>を指定します。
			</p>
<source><![CDATA[@Select(ensureResult = true)
Employee selectById(Integer id);]]></source>
			<p>
				検索結果が0件ならば<code>org.seasar.doma.jdbc.NoResultException</code>がスローされます。
			</p>
		</section>
		<section name="検索結果のマッピングの保証">
			<p>
				検索結果を受ける型がエンティティクラスやエンティティクラスを要素とする<code>java.util.List</code>の場合において、エンティティのプロパティすべてに対して漏れなく結果セットのカラムをマッピングすることを保証したい場合は、<code>@Select</code>の<code>ensureResultMapping</code>要素に<code>true</code>を指定します。
			</p>
<source><![CDATA[@Select(ensureResultMapping = true)
Employee selectById(Integer id);]]></source>
			<p>
				結果セットのカラムにマッピングされないプロパティが存在する場合<code>org.seasar.doma.jdbc.ResultMappingException</code>がスローされます。
			</p>
		</section>
		<section name="クエリタイムアウト">
			<p>
				<code>@Select</code>の<code>queryTimeout</code>要素にクエリタイムアウトの秒数を指定できます。
			</p>
<source><![CDATA[@Select(queryTimeout = 10)
List<Employee> selectAll();]]></source>
			<p>
				<code>queryTimeout</code>要素に値を指定しない場合、
				<a href="../config.html">設定クラス</a>に指定されたクエリタイムアウトが使用されます。
			</p>
		</section>
		<section name="フェッチサイズ">
			<p>
				<code>@Select</code>の<code>fetchSize</code>要素にフェッチサイズを指定できます。
			</p>
<source><![CDATA[@Select(fetchSize = 20)
List<Employee> selectAll();]]></source>
			<p>
				<code>fetchSize</code>要素に値を指定しない場合、
				<a href="../config.html">設定クラス</a>に指定されたフェッチサイズが使用されます。
			</p>
		</section>
		<section name="最大行数">
			<p>
				<code>@Select</code>の<code>maxRows</code>要素に最大行数を指定できます。
			</p>
<source><![CDATA[@Select(maxRows = 100)
List<Employee> selectAll();]]></source>
			<p>
				<code>maxRows</code>要素に値を指定しない場合、
				<a href="../config.html">設定クラス</a>に指定された最大行数が使用されます。
			</p>
		</section>
		<section name="マップのキーのネーミング規約">
			<p>
				検索結果を<code><![CDATA[java.util.Map<String, Object>]]></code>にマッピングする場合、
				<code>@Select</code>の<code>mapKeyNaming</code>要素にマップのキーのネーミング規約を指定できます。
			</p>
<source><![CDATA[@Select(mapKeyNaming = MapKeyNamingType.CAMEL_CASE)
List<Map<String, Object>> selectAll();]]></source>
			<p>
				<code>MapKeyNamingType.CAMEL_CASE</code>は、カラム名をキャメルケースに変換することを示します。
				そのほかに、カラム名を大文字や小文字に変換する規約があります。
				指定しない場合、変換は行われません。
			</p>
		</section>
	</body>
</document>