スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

S2Hibernateを試す

DIコンテナ+AOPのSeaserのプロジェクトのひとつにS2Hibernateがある。
これは、ORマッピングツールであるHibernateをSeaserに統合して、使いやすくしたものだ。以前、K氏に紹介してもらい、また@ITでもしばしば取り上げられるので試してみたいと思っていた。

自分で行っている家計簿のサンプルプロジェクトの中で利用してみた感想を述べたいと思う。これを試したのは、去年の11月だったが、なかなかブログに書く時間がなくて今ようやく書いてみることに。

このプロジェクト、アプリケーションのアーキテクチャーは、もともと、
プレゼンテーション層にStruts、そしてロジック層があり、データアクセス層にはDbUtilを使っていた。プレゼンテーション層からロジック層の呼び出しは、独自のコンテナでやっていた。個々のFactoryクラスを作るのは無駄だと思っていたし、昔からずっとこのやり方でやっていたので、またDIしなくても共通クラスを継承してもいいんじゃないという感じだった。親クラスの代わりに、メンバーに依存クラス(インターフェース)を持つわけで、それがインターフェースだろうが具象クラスだろうと何らかのものに依存することには変わりないのだから。
なので、DI+AOPを適用したときも、DIの部分では特に有り難味を感じることはなかった。AOPについては、ログやトランザクションで、データアクセス層がかなりすっきりするようになった。

DbUtilは、ROマッピングと言っていいと思う。ORは手動で行う必要がある。DbUtilだけでは不十分なのでひとつWrapperをかませているが。私は業務アプリに関してはDOAの人間なのでORマッピングの必要性は感じないし、これで十分だと思う。もっと小規模であれば、データクラスを作らずにMapで済ませてしまうのでも十分だと思う。

DbUtilを使っているときのOは、単なるDTO(データ転送用オブジェクト:単純なデータ格納クラス)で、ドメインモデルではない。
何が違うのかと言うと、ドメインモデルの場合、クラス図に描かれているような、他クラスとの関連が定義される。例えば、Groupクラスが、Userクラスを持っている場合、
class Group {
  Set<User> users;
  ....
}

class User {
  Group group;
  ....
}
となり、直接関連するオブジェクトへの参照を持つ。これがDTOの場合、
class User {
  String groupid;
}
となって、Groupクラスとの関連を持たない。テーブルのレコードをコピーしてきただけである。こうする場合、例えばUserオブジェクトから、グループ名を引き出したい場合、DTOであれば、あらかじめUserクラスに、
String groupname;
というメンバーを用意しておいて、データベースから値を取ってくる際に、UserテーブルとGroupテーブルをJOINして、グループ名を持ってくる必要がある。
一方、ドメインモデルの場合、その必要がなく、すでに参照はあるので、
user.getGroup().getName();
で持ってくることができる。なので、必要なときになってからGroupオブジェクトを取り出せばいい。DTOの場合、あらかじめDBに問い合わせておかなければいけない。

また、DTOの場合、テーブルのデータをコピーしているので同じインスタンスがメモリ上で重複する可能性がある。複数のユーザ情報を持ってきたとき、そのすべてにグループ名があることになる。ドメインモデルであれば、グループ名はGroupオブジェクトに1つあるだけで、Groupオブジェクトは重複していない。

こういった違いがある。ただこのドメインモデルの考えは理想的にであって、実際にこれをどう実現するのかは難しい。先ほど必要になってからGroupオブジェクトを取り出せばいいと述べたが、これはORマッピングの世界では遅延ローディングと言われているものだが、実際その使用にはいろいろと制限があり、プレゼンテーション層まで引っ張り回すのは推奨されていない。

私はこれでは利便さが失われてしまうと思う。DBのJOINを意識せずにできるのが利点だが、それが最も必要とされる場所で使えないとなると、大した利点ではなくなる。実際、サービス層での遅延ローディングもうまくいかなかった。ここはセッションを引き伸ばせばできたかもしれない。

また、オブジェクトの共有も、データベースにアクセスしているセッション内のみであって、アプリケーション全体ではない。結局、DTOにおけるコピーと大差ない。

むしろ、ドメインオブジェクトをプレゼンテーション層に渡すためのDTOに詰め替える作業が煩雑で、先のグループ名をセットするのに、
userDTO.setGroupName(user.getGroup().getName());
といちいち全部を変換する必要があり、これなら最初からデータベースをJOINして持ってきてセットした方が簡単だった。

再帰的な構造を持ったテーブル(オブジェクト)を扱っていた部分があって、それを画面に表示するときにツリー構造に直す必要があって面倒なロジックを組んでいたのだが、この点に関しては、このドメインモデルによって簡単に構造化できた。しかし、それをDTOに詰め替える作業で結局同じだけの長さのコードが必要になったが。

更新系についても、そう簡単にはいかなかった。createについてはよいが、updateの際に成功した行数を返し、対象がないときにはエラーメッセージを表示するようにしていたので単純なやり方ではうまくいかない。deleteも同じで、また論理削除をするやり方にしていたのでこれまた簡単にはいかない。

こう言うと、必ずそういう作りにしているのが悪いと言われる。所詮こういうツールはシンプルな使い方をより便利にするだけだ。少し変わった要求を持ち込むと途端に対応できなくなる。あるいは対応できるように拡張していくと、ひどくツールが複雑になって学習時間がかなり必要になる。

関連記事
スポンサーサイト

コメント

非公開コメント

プロフィール

dayan

Author:dayan
小職は、SE(システムエンジニア)を専門としておりますが、技術的な情報を中心に、それ以外に経済関連の日記、たわいもない日記も載せていきます。
[公式HPもよろしく!]

天気予報

-天気予報コム- -FC2-
リンク
ブロとも申請フォーム

この人とブロともになる

カテゴリー
最近の記事
ブログ内検索
最近のコメント
最近のトラックバック
RSSフィード
月別アーカイブ


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。