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コメントにより

  • dto.empno != nullの場合、"and empno = " + /*dto.empno*/の評価結果
  • dto.empno == nullの場合、何も生成されない

となる(7788はこのSQLSQL*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だ。