Employee Management4-(1)
/employee/employeeSearch.htmlの[create]ボタンから始まる一連の処理は前回までで片付いたので(?)、今度はの[search]ボタン追ってみる。employeeSearch.htmlそのもの、あるいは表示されるまでの仕組みはこちらを参照。ということで
<input type="button" value="search" m:action="#{employeeSearchAction.checkSearchCount}" onclick="location.href='employeeList.html'"/>
employeeSearchActionも一度見ているので、詳細な説明はパス。要はこのボタンが押されるとEmployeeSearchActionImpl#checkSearchCount()が呼び出されるということ。
public String checkSearchCount() { if (employeeLogic.getSearchCount(employeeSearchDto) == 0) { throw new BadCriteriaRuntimeException(); } return "employeeList"; }
なるほど。先に該当レコード数をチェックするのね。この場合employeeLogicにはテーブルEMPを操作するインタフェースEmployeeLogicを実装したクラスEmployeeLogicImpのインスタンスがセットされていて、employeeSearchDtoにはemployeeSearch.htmlへ入力された結果がValueBindingされている(sessionスコープ)。この辺の話はこっち。
そのgetSearchCount()は次のようにemployeeDtoDaoのgetSearchCount()を呼び出すだけ。
public int getSearchCount(EmployeeSearchDto dto) { return employeeDtoDao.getSearchCount(dto); }
employeeDtoDaoもテーブルEMPに関連付けられていて、getSearchCount()は以下の定義があるだけ。
public String getSearchCount_ARGS = "dto"; public int getSearchCount(EmployeeSearchDto dto);
ARGSアノテーションはgetEmployeeDto()メソッドの引数名をS2Daoに教えるもの。そしてこのメソッドの呼び出しで実行されるSQLはexamples/jsf/dao/Employee_getSearchCount.sql。 Daoと同じ場所(ディレクトリ)にあって、Daoのクラス名_メソッド名.sqlというネーミングルールに一致するから。中身は一見複雑に見える。
select count(*) from emp e left outer join dept d on e.deptno = d.deptno /*BEGIN*/ where /*IF dto.empno != null*/and empno = /*dto.empno*/7788/*END*/ /*IF dto.ename != null*/and ename = /*dto.ename*/'SCOTT'/*END*/ /*IF dto.job != null*/and job = /*dto.job*/'ANALYST'/*END*/ /*IF dto.mgr != null*/and mgr = /*dto.mgr*/7566/*END*/ /*IF dto.fromHiredate != null*/and hiredate >= /*dto.fromHiredate*/'1982-12-01'/*END*/ /*IF dto.toHiredate != null*/and hiredate <= /*dto.toHiredate*/'1982-12-31'/*END*/ /*IF dto.fromSal != null*/and sal >= /*dto.fromSal*/1000/*END*/ /*IF dto.toSal != null*/and sal <= /*dto.toSal*/4000/*END*/ /*IF dto.deptno != null*/and deptno = /*dto.deptno*/20/*END*/ /*END*/
なるほど。dtoのプロパティがnullでなければ、つまりemployeeSearch.htmlで何らかの値が入力されていれば、それを検索条件として追加する。たとえば
/*IF dto.empno != null*/and empno = /*dto.empno*/7788/*END*/
の場合、IFコメントにより
となる(7788はこのSQLをSQL*Plusなどのツールで実行するとき場合に使われる値)。そしてBEGINコメントで
/*BEGIN*/WHERE句/*END*/
という形になっているから、WHERE句内のIFコメントがすべてfalseならWHERE句自体生成しない。ということになっているが、このBEGINコメントの働きには他にも何かあるそう。上のIFコメントの場合、条件がtrueであれば"and empno = ... "が生成されるはずだが、実際には"and"がない。つまり"where empno = ..."が返される。確かにwhereの次にandが来たら文法エラーだから、これでいいんだけどね(getSearchCount.sqlをHSQL Database Managerで実行するとそれが原因でエラーになる)。この辺はリファレンスにも書いてないような気がする。他にもBEGINコメントの機能はあるのかな?
まぁともかくこのSQLが実行されると該当レコード件数が返る(count(*)だから該当がない場合でも0が返される)。この結果でcheckSearchCount()は
- 該当レコードがなければ例外BadCriteriaRuntimeExceptionをスローする。画面はemployeeSearch.htmlのまま。
- 該当あれば"employeeList"を返す。この結果、/employee/employeeList.htmlへ遷移する。
という分岐を行う。なるほど。次はemployeeList.htmlだ。