13.3. Query オブジェクト
データベース内の
Person インスタンスの全一覧が必要な場合は Query オブジェクトを以下のように使うことができます。
<framework:entity-query name="people" ejbql="select p from Person p"/>
JSF ページからそれを使うことができます。
<h1>List of people</h1>
<h:dataTable value="#{people.resultList}" var="person">
<h:column>
<s:link view="/editPerson.jsp"
value="#{person.firstName} #{person.lastName}">
<f:param name="personId" value="#{person.id}"/>
</s:link>
</h:column>
</h:dataTable>
ページネーションに対応させる必要がある場合は
<framework:entity-query name="people" ejbql="select p from Person p"
order="lastName" max-results="20"/>
表示するページを決めるページパラメータを使います。
<pages>
<page view-id="/searchPerson.jsp">
<param name="firstResult" value="#{people.firstResult}"/>
</page>
</pages>
ページネーションを管理する JSF のコードは若干繁雑ですが許容範囲内です。
<h1>Search for people</h1>
<h:dataTable value="#{people.resultList}" var="person">
<h:column>
<s:link view="/editPerson.jsp"
value="#{person.firstName} #{person.lastName}">
<f:param name="personId" value="#{person.id}"/>
</s:link>
</h:column>
</h:dataTable>
<s:link view="/search.xhtml" rendered="#{people.previousExists}"
value="First Page">
<f:param name="firstResult" value="0"/>
</s:link>
<s:link view="/search.xhtml" rendered="#{people.previousExists}"
value="Previous Page">
<f:param name="firstResult" value="#{people.previousFirstResult}"/>
</s:link>
<s:link view="/search.xhtml" rendered="#{people.nextExists}"
value="Next Page">
<f:param name="firstResult" value="#{people.nextFirstResult}"/>
</s:link>
<s:link view="/search.xhtml" rendered="#{people.nextExists}"
value="Last Page">
<f:param name="firstResult" value="#{people.lastFirstResult}"/>
</s:link>
実際の検索画面ではユーザーはオプションで検索基準を入力でき、検索結果を絞りこむことができます。Query オブジェクトを使うとこのユースケースに対応するオプションの制約を指定できます。
<component name="examplePerson" class="Person"/>
<framework:entity-query name="people" ejbql="select p from Person p"
order="lastName" max-results="20">
<framework:restrictions>
<value>
lower(firstName) like lower(concat(#{examplePerson.firstName},'%&'))
</value>
<value>
lower(lastName) like lower(concat(#{examplePerson.lastName},'%&'))
</value>
</framework:restrictions>
</framework:entity-query>
上記の例では「example」オブジェクトの使用について留意してください。
<h1>Search for people</h1>
<h:form>
<div>
First name: <h:inputText value="#{examplePerson.firstName}"/>
</div>
<div>
Last name: <h:inputText value="#{examplePerson.lastName}"/>
</div>
<div>
<h:commandButton value="Search" action="/search.jsp"/>
</div>
</h:form>
<h:dataTable value="#{people.resultList}" var="person">
<h:column>
<s:link view="/editPerson.jsp"
value="#{person.firstName} #{person.lastName}">
<f:param name="personId" value="#{person.id}"/>
</s:link>
</h:column>
</h:dataTable>
元となるエンティティが変更されたときにそのクエリをリフレッシュするには
org.jboss.seam.afterTransactionSuccess イベントを監視します。
<event type="org.jboss.seam.afterTransactionSuccess">
<action execute="#{people.refresh}" />
</event>
または、
PersonHome で person エンティティの永続化、 更新、または削除が行われた場合にクエリをリフレッシュする場合は次のようにします。
<event type="org.jboss.seam.afterTransactionSuccess.Person">
<action execute="#{people.refresh}" />
</event>
残念ながら、Query オブジェクトは join fetch のクエリとはうまく動作しません。これらのクエリでのページネーションの使用は推奨しません。
getCountEjbql() を無効化して、結果の合計数を計算する独自の方法を実装する必要があります。
本項の例はすべて設定による再利用を示していますが、拡張により再利用を行うことも同様に可能です。