パターン4ではDAO、DTOを使っています。ちょっと今までのパターンを復習してみます。
- パターン1
- 1 Action-1 ActionForm。1 JSP – n Actionで作成。
DAO, DTOは作成しない - パターン2
- パターン1に加えて、アクション切り替えのフラグを使用。
JSP内でアクションを切り替える - パターン3
- 1 JSP – 1 Action – 1 ActionForm。DispatchActionを使用。
1画面内のイベントを1つのActionで記述する。DAO,DTOは使用しない。 - パターン3B
- パターン3の方法を発展させ、EasyDispatchActionを使用。
パターン3と比べて、イベント制御のコマンド文字列をJavaScriptで切り替える必要がなくなる
パターン4では、パターン3Bを発展させて、DAOとDTOを使用しています。
あまり変化はありませんが、ロバストネス図は、次のようになります。
また、前提条件の資料は以下のとおりです。
画面的にはパターン3と変わりありません。
DAOについて
DAOはSQLを発行するだけの、ユーティリティメソッド群として作成しました。
ちまたのO/Rマッピングツールのように、データ構造にアクセスするための永続化オブジェクトのようなものは作成しません。
その理由は、SQLでデータアクセスはできるが、オブジェクト指向を知らない開発者を考慮したためです。
例えばHibernateや、EJBの永続化オブジェクトのような設計すれば、SQLを使わずとも、ビジネス上のデータ構造にマッチした形で取得できると思います。でも、このパターンではSQLを重視して単なるSQL発行→データ取得の関数としました。
したがって、状態を持ったインスタンスである必要はないので、メソッドはすべてstaticメソッドとしました。
無意味に、インスタンスをnewして、SQLを発行させるだけのオブジェクトを作る必要はないと思います。
パターン3Bと比べて、Actionに記述されていたデータアクセス処理がなくなり、Actionの処理はすっきりしました。
DAOを作成する単位は、オブジェクト指向で頭を悩ませたりしないように、1 DAO – 1 テーブルの単位で作成します。
検索で結合するようなケースは、主となるテーブルを1つ決め、そのテーブルのDAOとして記述するルールとします。(このサンプルプログラムでは単純すぎて無いですが)
DTOについて
パターン3までは検索結果は、Mapを使って格納していましたが、パターン4では、専用のJavaBeanを用意しました。DBのテーブルの型に合った形のBeanを使ってロジックを記述できるので、スペルミスが減り、タイプセーフになります。
DTOは、Productsテーブルのデータ構造とマッチするように作ってありますが、似たような構造があるからといって、あまり頭を悩ませて共通化しなくてもよいと思います。多少冗長であっても、どんどん作っていいのではないでしょうか。
共通化や抽象化して、無駄のないように作ったのに、仕様変更で青ざめるよりは、悩まずガンガンコピって作成し、仕様変更発生時には検索と置換で単純作業的に修正し、再テストしたほうが素早く開発できるという考えです。
DBUtilsを使うことで、検索結果をDTOに格納した形で、Listとして返してくれます。
QueryRunner run = new QueryRunner();
ResultSetHandler h = new BeanListHandler(ProductRecord.class);
//検索結果の各レコードを、Beanに格納し、その全レコード分をListとして取得する
List resultList = (List)run.query(
conn, "select * from products", h);
1レコード分の情報が、JavaBeanに格納され、それの集合体がListとして作成されます。
DAOはあくまでDTOを使った結果を返すようにします。これはDAOはStrutsだけで使用されるクラスではなく、その他のビジネスロジックからも使えるものと考えたためです。
したがって、DaoではActionFormが現れてはいけません。ActionFormにデータを詰め込んだり、ActionFormを引数に使った時点で、Strutsからしか使えないDAOになってしまいます。
DAOがDTOを返すとなると、Actionでは、DTO→ActionFormへの詰め替えが発生します。
これは大部分が、DTOの内容をそのまま右から左へと移し替えるだけです。場合によっては、HTMLで表示するための、書式変換をしたりします。
詰め替え作業は単調で、手作業でコーディングするのがわずらわしい処理ですが、これはBeanUtilsを使うと、非常に簡単に処理できます。
BeanUtils.copyProperties(editForm, record);
これで、型変換も含めて自動的にコピーしてくれます。
(ただし、型変換はあまり期待しないほうがよいです。String→Dateなどは期待通りに機能しない)
ActionFormからDTOに詰め替えてDAOを実行。結果として取得したDTOを、ActionFormに詰め替え。ということができます。
開発パターン4
- DTOはあまり共通化を意識せず、伸び伸びと作成する
- DAOはテーブル単位で作成、SQLを発行するstaticメソッドを持つ
- DispatchActionクラスを継承して作成する
- 1 JSP-1 Action-1 ActionFormのルールで作成(ActionFormのないActionも可)
- 画面内のイベントを、1 Actionで全て記述する
ソースコードはこちらです。(kenkyu04パッケージが今回の対象です)
Struts開発パターン4 ソースコード
2007/09/13追記
サンプルソースコードが解説の図のような構成になっておらず、一覧画面から直接編集画面を呼び出すような動作になっておりましたので、ソースコードを修正しました。
サンプルのstuts-config.xmlのaction-chainでXXXX.do?cmd=XXXXを使用していますがEasyDispatchActionでは_XXXX_でメソッドパターンを指定しています。
これで動作するのでしょうか?
サンプルを動作させていないので間違いでしたらすみません。
ご指摘ありがとうございます。
おっしゃるとおりで、パターン03の設定が残ったままになっていました。
動いてはいたのですが、上記の解説図のようには動いておらず、パターン3と同じように動作していました。ソースは修正しました。