SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

OSSフレームワーク「dataforms.jar」でサンプルプログラムを構築する(3)

  • X ポスト
  • このエントリーをはてなブックマークに追加

 本記事ではMVCそれぞれの機能を1つのjarファイルにまとめた、中小規模Webアプリ開発向けのOSSフレームワーク「dataforms.jar」を使い、掲示板のサンプルアプリケーションを構築します。前回は検索条件の調整を行い、添付ファイルテーブルの操作機能を追加しました。今回は記事管理ページを完成に持っていきます。

  • X ポスト
  • このエントリーをはてなブックマークに追加

はじめに

 前回は検索処理を改善し、添付ファイルテーブルの処理を追加しました。今回はスレッド指定や検索結果リストの改善を行い、リリース用の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クラスを作成します。

「ThreadSingleSelectField.java」の内容
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を新たに追加します。

「ArticleEditForm.java」の修正箇所
/**
 * コンストラクタ。
 */
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>”に変更します。

「ArticleEditForm.html」の修正箇所
    <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は以下の通りスレッドを指定できるようになります。これでスレッドを指定して記事を登録すると、指定されたスレッド内の記事として登録されるようになります。スレッドを指定しなければ、今まで通り新規スレッドの登録になります。

スレッドプルダウンの動作
スレッドプルダウンの動作

次のページ
スレッドフィールドの実装(2)

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

高柳 正彦(タカヤナギ マサヒコ)

経験年数30年を超えた、システムエンジニアです。一応管理職のはずですが、未だにコードを書いています。この仕事を長々とやっていると、それなりにノウハウがたまってきます。そのノウハウをまとめたものができないかと思い、独自のフレームワークを作り始めました。そのフレームワークもそれなりに使えるようになってき...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/10124 2017/05/29 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング