スレッドフィールドの実装(2)
スレッド内の記事を登録できるようになったので、検索条件にスレッドを追加し、結果の一覧にスレッド名を表示するようにします。まず、ArticleQueryForm.javaにThreadSingleSelectFieldを追加し、そのフィールドIDを“threadId”とします。
/** * 問い合わせフォームクラス。 */ public class ArticleQueryForm extends QueryForm { /** * コンストラクタ。 */ public ArticleQueryForm() { ArticleTable table = new ArticleTable(); this.addField(new ThreadSingleSelectField(ArticleTable.Entity.ID_THREAD_ID)); this.addField(table.getTitleField()).setMatchType(MatchType.PART); this.addField(table.getAutherField()).setMatchType(MatchType.PART); this.addField(table.getContentsField()).setMatchType(MatchType.PART); } }
これに対応する「ArticleQueryForm.html」にも、以下の通りスレッドを選択するための<select>を追加します。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <form id="queryForm"> <div class="formHeader">検索条件</div> <table class="responsive"> <tbody> <tr> <th>スレッド</th> <td><select id="threadId"></select></td> </tr> <tr> <th>記事タイトル</th> <td><input type="text" id="title" /></td> </tr> <tr> <th>著者</th> <td><input type="text" id="auther" /></td> </tr> <tr> <th>本文</th> <td><input type="text" id="contents" /></td> </tr> </tbody> </table> <input type="submit" id="queryButton" value="検索"> <input type="button" id="resetButton" value="リセット"> <input type="button" id="newButton" value="新規登録"> </form> </body> </html>
Queryクラスは、QueryFormのフィールドリストとPOSTされたデータから自動的に条件式を作成するので、この修正だけでスレッドを限定することができるようになります。
次に、ArticleQueryResultForm中の記事一覧にスレッド名を表示します。まず、「ArticleDao.java」中のArticleTableQueryを以下の通り修正し、スレッド名を取得するようにします。
/** * QueryFormで指定した条件で行う問い合わせクラスです。 */ public static class ArticleTableQuery extends Query { private static final String THREAD_ALIAS = "th"; public static final String ID_THREAD_NAME = "threadName"; /** * コンストラクタ。 */ public ArticleTableQuery() { SubQuery thread = new SubQuery(new ThreadQuery()); thread.setAlias(THREAD_ALIAS); Table table = new ArticleTable() { @Override public String getJoinCondition(final Table joinTable, final String alias) { if (THREAD_ALIAS.equals(alias)) { return this.getLinkFieldCondition(ArticleTable.Entity.ID_THREAD_ID, joinTable, alias, ArticleTable.Entity.ID_THREAD_ID); } return super.getJoinCondition(joinTable, alias); } }; this.setFieldList(table.getFieldList()); this.getFieldList().addField(new AliasField(ID_THREAD_NAME, thread.getField(ArticleTable.Entity.ID_TITLE))); this.setMainTable(table); this.setJoinTableList(new TableList(thread)); } }
この修正では、ThreadQueryのサブクエリを作成してArticleTableとJoinするようにしています。SubQueryクラスはTableクラスから派生しているクラスで、指定されたQueryをテーブルと同様にJoinさせることができます。テーブル設計時に決まるテーブル間結合の条件式は、XxxTableRelation.javaに設定しておきます。しかし、今回のように専用のクラスを作っていないサブクエリとの結合条件式は、ArticleTableの無名クラスでgetJoinConditionメソッドをオーバーライドしたほうが書きやすいと思います。
さらに、修正されたArticleTableQueryでは、AliasFieldを使用してThreadQueryのtitleフィールドにthreadNameという別名を設定しています。[開発ツール/問合せ実行]を使用して、ArticleTableQueryクラスから作成されるSQLを確認すると以下のようになっています。ThreadQueryをJoinし、スレッド名を取得するSQLになっていることが確認できます。
select m.article_id as article_id ,m.thread_id as thread_id ,m.title as title ,m.auther as auther ,m.contents as contents ,m.delete_flag as delete_flag ,m.create_user_id as create_user_id ,m.create_timestamp as create_timestamp ,m.update_user_id as update_user_id ,m.update_timestamp as update_timestamp ,th.title as thread_name from article as m inner join (select m.article_id as article_id ,m.thread_id as thread_id ,m.title as title ,m.auther as auther ,m.contents as contents ,m.delete_flag as delete_flag ,m.create_user_id as create_user_id ,m.create_timestamp as create_timestamp ,m.update_user_id as update_user_id ,m.update_timestamp as update_timestamp from article as m where m.thread_id = m.article_id and m.delete_flag='0' ) as th on m.thread_id=th.thread_id and th.delete_flag='0' where m.delete_flag='0'
ArticleTableQueryがスレッド名称(ID:threadName)を返すようになったので、以下の通り「ArticleQueryResultForm.java」と「ArticleQueryResultForm.html」を修正します。
/** * コンストラクタ。 */ public ArticleQueryResultForm() { ArticleTable table = new ArticleTable(); this.addPkFieldList(table.getPkFieldList()); PageScrollHtmlTable htmltable = new PageScrollHtmlTable(Page.ID_QUERY_RESULT, ArticleDao.getQueryResultFieldList()); htmltable.getFieldList().get(ArticleTableQuery.ID_THREAD_NAME) .setSortable(true); htmltable.getFieldList().get(ArticleTable.Entity.ID_TITLE).setSortable(true); htmltable.getFieldList().get(ArticleTable.Entity.ID_AUTHER).setSortable(true); htmltable.getFieldList().get(ArticleTable.Entity.ID_CONTENTS).setSortable(true); this.addHtmlTable(htmltable); }
<form id="queryResultForm"> <div class="formHeader">検索結果</div> <input type="hidden" id="articleId" /> <table class="responsive"> <tbody> </tbody> </table> <div class="hScrollDiv"> <table id="queryResult"> <thead> <tr> <th> No. </th> <th> スレッド </th> <th> 記事タイトル </th> <th> 著者 </th> <th> 本文 </th> <th> 操作 </th> </tr> </thead> <tbody> <tr> <td> <span id="queryResult[0].rowNo"></span> <input type="hidden" id="queryResult[0].articleId" /> <input type="hidden" id="queryResult[0].threadId" /> <input type="hidden" id="queryResult[0].createUserId" /> <input type="hidden" id="queryResult[0].createTimestamp" /> <input type="hidden" id="queryResult[0].updateUserId" /> <input type="hidden" id="queryResult[0].updateTimestamp" /> </td> <td> <span id="queryResult[0].threadName"></span> </td> <td> <a id="queryResult[0].updateButton" href="JavaScript:void(0);"><span id="queryResult[0].title"></span></a> </td> <td> <span id="queryResult[0].auther"></span> </td> <td> <span id="queryResult[0].contents"></span> </td> <td> <input type="button" id="queryResult[0].viewButton" value="表示"> <input type="button" id="queryResult[0].referButton" value="参照登録"> <input type="button" id="queryResult[0].deleteButton" value="削除"> </td> </tr> </tbody> </table> </div> </form>
この状態でスレッドを指定して検索すると、以下の画面になります。