SHOEISHA iD

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

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

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

特集記事

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

データ読み込み処理の実装

 ArticleQueryResultFormで記事をクリックしてArticleEditFormを表示するときは、ArticleDaoのMap<String, Object> query(final Map<String, Object> data)メソッドを呼び出して編集データを読み込みます。このメソッドに保存された添付ファイルを読み込む処理を追加します。

AttachFileTableの保存処理の追加
package bbs.dao;

    ・・・ 中略 ・・・

/**
 * Daoクラス。
 *
 */
public class ArticleDao extends Dao {
    /**
     * Logger.
     */
    private static Logger logger = Logger.getLogger(ArticleDao.class);

    ・・・ 中略 ・・・

    
    /**
     * 添付ファイルテーブルの問い合わせクラスです。
     *
     */
    public static class AttachFileQuery extends Query {
        /**
         * コンストラクタ。
         */
        public AttachFileQuery() {
            AttachFileTable table = new AttachFileTable();
            this.setFieldList(table.getFieldList());
            this.setMainTable(table);
            this.setOrderByFieldList(new FieldList(table.getSortOrderField()));
        }
    }

    
    /**
     * PKでレコードを限定し、データを取得します。
     * @param data 条件データ PKの情報を全て含むマップ。
     * @return ヒットしたレコード。
     * @throws Exception 例外。
     */
    public Map<String, Object> query(final Map<String, Object> data) throws Exception {
        Query query = new ArticleTableQuery();
        query.setQueryFormFieldList(query.getMainTable().getPkFieldList());
        query.setQueryFormData(data);
        
        Map<String, Object> map =  this.executeRecordQuery(query);
        Query fquery = new AttachFileQuery();
        fquery.setQueryFormFieldList(new FieldList(query.getMainTable().getPkFieldList().get(0)));
        fquery.setQueryFormData(data);
        List<Map<String, Object>> list = this.executeQuery(fquery);
        map.put("attachFileTable", list);
        return map;
        
    }

    ・・・ 後略 ・・・

}

 この修正ではAttachFileTableを読み込むためにAttachFileQueryクラスを作成しています。このQueryクラスは"select * from attach_file order by sort_order asc"というSQLに相当します。ArticleDaoのqueryメソッドではArticleTableのデータを読み込んだ後、このQueryクラスを使用して添付ファイルのリストを取得しています。このとき、取得の条件に指定するフィールドは先頭の主キー項目である記事ID(ID:articleId)のみにします。このように条件を指定することによって、指定された記事に添付されたファイルのみ取得できるようになります。戻り値となるマップには、"attachFileTable"という名前で添付ファイルリストを保存しておきます。

 今までの操作で作成したArticleTableのレコードのスレッドIDは全てnullになっています。そのため既存のデータを全て削除し、新たにデータを入力してください。また添付ファイルも追加して保存してください。

 新規入力後、[開発ツール/問い合わせ実行]を使うと、ArticleTableの登録内容を確認することができます。「記事ID=スレッドID」のレコードが登録されていることが分かります。

ArticleTableの登録内容
ArticleTableの登録内容

 この例ではArticleDao$ArticleTableQueryクラスを指定して、このクラスが作成するSQLを実行しています。このページではpublicなQueryクラスを指定して対応するSQLを確認することや、そのSQLを実行することができます。また、Queryクラスの指定は行わずにSQLを直接実行することもできます。

 記事の一覧から添付ファイルを登録した記事をクリックすると、以下のように添付ファイル一覧も表示されます。添付ファイルの一覧はjQuery-uiのsortable機能を使用し、行をドラッグすることによって順序を変更することができます。このとき各行に含まれている "<input type="hidden" id="attachFileTable[x].sortOrder" />"の値を先頭からふり直してくれます。そのため、このテーブルをそのまま登録するだけで、添付ファイルの並び順も保存される仕掛けになっています。

添付ファイルリストの読み込み結果
添付ファイルリストの読み込み結果

ページデザインの改善

 記事の本文のフィールド(ContentsField)はVarcharFieldから派生していいるため、<input type="text" .../>が生成されています。記事の内容は複数行テキストにしたいので、<textarea></textarea>に変更します。VarcharFieldから派生したフィールドは、そのidが一致していれば、<input type="text" .../> と<textarea></textarea>のどちらでも動作します。

「ArticleEditForm.html」の修正箇所
      <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 style="height: 110px;"><textarea id="contents" style="height: 100px;"></textarea></td>
          </tr>
          
        </tbody>
      </table>

必須バリデータの追加

 datafroms.jarの各種フィールドには適切なバリデータが設定されています。大抵の場合、必須バリデータを追加するだけで適切なバリデーションが行われるようになります。ArticleEditFormのコンストラクタを以下の通り修正してください。

「ArticleEditForm.java」の修正箇所
    /**
     * コンストラクタ。
     */
    public ArticleEditForm() {
        ArticleTable table = new ArticleTable();
        this.addTableFields(table);
        
        // 必須バリデータの登録
        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);
    }

 この修正では必須入力フィールドにRequiredValidatorを追加しています。この修正を実行すると以下のように必須チェックが行われます。

必須バリデータの動作
必須バリデータの動作

 上の画面を見ると気づかれると思いますが、RequiredValidatorを持つフィールドに対応するラベルには、自動的に必須マーク(*)が付きます。

さいごに

 前回の記事では開発ツールを使用してArticleTableを作成しました。その際、1フィールドごとにJavaのクラスができていることを説明しました。この解説を読んで「なぜ無駄にフィールドクラスを生産するのだろう?」と思った方も多いと思います。実際、dataforms.jarを使った開発では、大量のフィールドクラスができあがります。

 通常の業務システムを作っていると、1種類のフィールドが複数のデータベーステーブル、複数のフォームに配置されます。今までのフレームワークでは、データの保存形式はフィールドが配置された複数のデータベーステーブルのcreate table文で定義され、入力時のイベント処理は、フィールドが配置された全てのフォームに記述することになると思います。dataforms.jarのフィールドクラスは、Javaでその保存形式やサーバー側の各種処理を定義し、JavaScript側で入力時のイベント処理等を定義する構造になっています。このフィールドクラスを利用すれば、データ保存形式や入力時のイベント処理を1つのクラスにまとめて記述することができます。

 システムの開発が進むと、「このフィールドの桁数を増やしてほしい」「このフィールドではオードコンプリートで入力候補を出してほしい。」などの要求が次々と出てきます。こういった要求はテスト工程で出てきて、もめごとになるのが定番です。なぜもめるかというと、修正の工数が大きいからです。dataforms.jarでは、このような要求にも問題なく対応することができます。前者の要求は、フィールドクラスの桁数を変更し、開発ツールのテーブル管理で構造が変わったテーブルを一括して更新するだけで完了です。後者の要求は、該当フィールドクラスのオートコンプリートを有効にし、その入力候補を検索するための処理を作成するだけです。この修正だけで、フィールドが配置された全てのフォームでオートコンプリートが動作します。

 今回の記事ではフィールドクラスをカスタマイズすることによって、かなり複雑なUIが作れることを説明しました。次回の記事では不足している機能を追加し、記事管理ページを完成させます。その過程で、フォームクラスのカスタマイズやサブクエリを使った複雑な問い合わせ等を解説する予定です。

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

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
特集記事連載記事一覧

もっと読む

この記事の著者

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

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

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

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

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/10043 2017/05/22 14:00

イベント

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

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

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

メールバックナンバー