はじめに
前回は検索処理を改善し、添付ファイルテーブルの処理を追加しました。今回はスレッド指定や検索結果リストの改善を行い、リリース用のWARファイルを作成する手順を解説します。
対象読者
この記事を読むために必要な知識は以下の通りです。
- Java
- JavaScript
- jQuery、jQuery UI
- HTML、CSS
- SQL
必要な環境
dataforms.jarを使用した開発では、以下のものを使用しています。
- JDK1.8
- Eclipse 4.5以上
- Tomcat 7以上
スレッドフィールドの実装(1)
現段階のArticlePageはスレッドの先頭記事しか作成することができません。そこでスレッド中の記事を作成するために、スレッドIDを指定して記事を登録する機能を作っていきます。まず、スレッドの一覧を作成するメソッドを「ArticleDao.java」に追加します。
/** * Daoクラス。 * */ public class ArticleDao extends Dao { /** * Logger. */ private static Logger logger = Logger.getLogger(ArticleDao.class); ・・・ 中略 ・・・ /** * スレッドの先頭記事を取得するための問い合わせクラスです。 */ public static class ThreadQuery extends Query { /** * コンストラクタ。 */ public ThreadQuery() { Table table = new ArticleTable(); this.setFieldList(table.getFieldList()); this.setMainTable(table); this.setCondition("m.thread_id = m.article_id"); } } /** * スレッド一覧を取得します。 * @return スレッド一覧。 * @throws Exception 例外。 */ public List<Map<String, Object>> queryThreadList() throws Exception { Query query = new ThreadQuery(); return this.executeQuery(query); } ・・・ 中略 ・・・ }
ThreadQueryクラスは、ArticleTableを「スレッドID=記事ID」という条件式を指定して検索するようになっています。“m.thread_id”のように“m.”と指定されているのは、setMainTableで指定したテーブルの別名が“m”となっているためです。setMainTableに設定するテーブルは、setAliasで別名を指定しなかった場合、“m”という別名が自動的に設定されるようになっています。
条件式を直接記述する方法
QueryクラスはQueryFormの情報から検索条件を自動的に生成する方法だけでなく、上記のようにsetConditionメソッドで、直接条件式を指定することができます。
QueryFormからの条件とsetConditionの条件式が両方指定された場合、それぞれの条件をANDで結合した条件式を作成します。
HTML中のidアトリビュートやJavaで処理するマップ中のフィールドIDは、“fieldId”のようにキャメルケースを使用しています。これに対しSQLで使用するカラム名は、大文字、小文字の区別がない場合が多いので、“field_id”のようにスネークケースに変換して処理します。このため、setConditionメソッドで指定する条件式はキャメルケースではなく、スネークケースで指定する必要があります。
このメソッドを利用して、スレッドIDを選択するフィールドを作成します。以下の通り、SingleSelectFieldクラスから派生したThreadSingleSelectFieldクラスを作成します。
package bbs.field; ・・・ 中略 ・・・ /** * スレッド選択フィールド。 * */ public class ThreadSingleSelectField extends SingleSelectField<Long> { ・・・ 中略 ・・・ @Override public void init() throws Exception { super.init(); // スレッドの一覧を選択肢とします。 List<Map<String, Object>> olist = queryOptionList(); this.setOptionList(olist, true); } /** * スレッド一覧を取得します。 * @return スレッド一覧。 * @throws Exception 例外。 */ private List<Map<String, Object>> queryOptionList() throws Exception { ArticleDao dao = new ArticleDao(this); List<Map<String, Object>> list = dao.queryThreadList(); List<Map<String, Object>> olist = new ArrayList<Map<String, Object>>(); for (Map<String, Object> m: list) { Map<String, Object> o = new HashMap<String, Object>(); o.put("value", m.get(ArticleTable.Entity.ID_ARTICLE_ID)); o.put("name", m.get(ArticleTable.Entity.ID_TITLE)); olist.add(o); } return olist; } /** * {@inheritDoc} * <pre> * フォームから入力されたデータをLongに変換します。 * </pre> */ @Override public void setClientValue(final Object v) { if (!StringUtil.isBlank(v)) { this.setValue(Long.parseLong(((String) v).replaceAll(",", ""))); } else { this.setValue(null); } } /** * {@inheritDoc} * <pre> * DBから取得したデータをLongに変換します。 * </pre> */ @Override public void setDBValue(final Object value) { this.setValue(NumberUtil.longValueObject(value)); } }
このフィールドクラスでは、initメソッドでスレッドの一覧を取得し、選択肢として設定しています。その他、setClientValueとsetDBValueといったメソッドが実装されています。
Webのフォームから入力されたデータは、大抵文字列のままです。そのため、数値項目はいったん数値に変換して処理する必要があります。こういった変換処理は簡単な処理ですが、項目が多くなるとコーディングの手間もかかり、ソースの可読性が落ちていきます。そのため、dataforms.jarではフィールドクラスがデータの変換を行うようになっています。このフィールドが取り扱うデータの型はLongであるため、フォームから送信されたデータはsetClientValueでLongに変換され、データベースから読み込まれたデータはsetDBValueでLongに変換されます。EditFormのinsertDataやupdateDataメソッドに渡されるマップ中には、フィールドクラスによって変換された値が入ってきます。
この段階で、ArticleEditFormにはThreadIdFieldクラスのフィールドが配置されています。そこで、ThreadIdFieldクラスのフィールドを削除し、ThreadSingleSelectFieldを新たに追加します。
/** * コンストラクタ。 */ public ArticleEditForm() { ArticleTable table = new ArticleTable(); this.addTableFields(table); // スレッドIDの入力フィールドの入れ替え table.getFieldList().remove(ArticleTable.Entity.ID_THREAD_ID); this.addField(new ThreadSingleSelectField(ArticleTable.Entity.ID_THREAD_ID)); // 必須バリデータの登録 this.getFieldList().get(ArticleTable.Entity.ID_TITLE).addValidator(new RequiredValidator()); this.getFieldList().get(ArticleTable.Entity.ID_AUTHER).addValidator(new RequiredValidator()); this.getFieldList().get(ArticleTable.Entity.ID_CONTENTS).addValidator(new RequiredValidator()); // 添付ファイル指定用のテーブルをフォームに配置します。 AttachFileTable aft = new AttachFileTable(); EditableHtmlTable tbl = new EditableHtmlTable("attachFileTable", aft.getFieldList()); this.addHtmlTable(tbl); }
ArticleTable中のスレッドIDは、RecordIdFieldクラスから派生したフィールドになっています。RecordIdFieldクラスは、基本的にシーケンス等で自動生成される主キー用のフィールドで、開発ツールでHTMLに展開する場合、<input type="hidden" ... />と展開されます。このため、「ArticleEditForm.html」のスレッドIDは“<input type="hidden" id="threadId" />”になっています。今回の修正でこれを削除し、“<select id="threadId"></select>”に変更します。
<form id="editForm"> <div class="formHeader"><span id="editFormTitle"></span></div> <input type="hidden" id="saveMode" /> <input type="hidden" id="articleId" /> <!-- <input type="hidden" id="threadId" /> --> <input type="hidden" id="deleteFlag" /> <input type="hidden" id="createUserId" /> <input type="hidden" id="createTimestamp" /> <input type="hidden" id="updateUserId" /> <input type="hidden" id="updateTimestamp" /> <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>
このソースをビルドして実行すると、ArticleEditFormは以下の通りスレッドを指定できるようになります。これでスレッドを指定して記事を登録すると、指定されたスレッド内の記事として登録されるようになります。スレッドを指定しなければ、今まで通り新規スレッドの登録になります。