2012年6月18日月曜日

Hibernate Session スコープ戦略 1/3 (理論編)

Hibernate を利用した場合のドメインオブジェクトの同期範囲の扱いについて、日本語リソースが少ないため、ここで解説しておきます。 ブログという都合上かなり簡略化して書いている部分もあります。 Hibernate の Session のスコープをどう扱うかという戦略(Session スコープ戦略 / Session 引き回し戦略 とでも言いましょうか)についてです。 Hibernate + Spring を基本に書いています。

Hibernate の Session は、 Spring と一緒に利用するとき、基本的にはトランザクションが終了すると Session も閉じることになり、エンティティ(ドメインオブジェクト)と SessionFactory の同期が外れます(*1)。 
*1 同期が外れていることを分離(detach)と言います。分離しているエンティティを分離オブジェクト(detached object)と言います。
Lazy Loading (レイジーローディング) を利用しているとき(これは Hibernate の default 設定)、トランザクション終了した(Session が閉じた)あとにエンティティのトランザクション開始時から実行していない getter を実行すると、以下のような LazyInitializationException が発生することになります。

org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:86)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:140)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
...

 そして、このままであると不都合があります。
  1. 画面で随時取りたい項目が取れない(画面では LazyLoading が利用できない)
  2. 画面間で同じドメインオブジェクトを利用するにしても再度取得しないといけない(画面間楽観排他)
もし分散処理で業務処理と画面処理が SOAP などのプロトコルを介して分かれているなら、事前に getter を動かしておく、 Eager Fetch で取得しておくなどして、甘んじて受け入れることになりますが、同じ筐体であれば解決したいところです。 すなわち、ドメインオブジェクトの値を取得したいその間に Session を開いたままにしておくことができれば、この問題は解決できます。Hibernate の Session を開いたまま引き回すということです。 Hibernate の Session を引き回す戦略は、2つあります。
  1. Open Session In View (OSIV) オープン・セッション・イン・ビュー
  2. Flow Managed Persistence (FMP) フロー・マネジド・パーシスタンス
1. の OpenSessionInView (OSIV) とは、 一度のリクエストからレスポンスの範囲で Session を開いたままにするという設計戦略です。この戦略には、 Spring Framework で用意している OpenSessionInViewFilter を利用すると別途実装なしに設定できます。不都合の 1. に対応します。 2. の Flow Managed Persistence (FMP) とは、複数画面を跨いで自由に設定した範囲で Session を開いたままにするという設計戦略です。この戦略には、 Spring Web Flow (SWF) を利用すると別途実装なしに設定できます。 SWF のスコープを利用してその範囲で Session を開いたままにします。不都合の 2. に対応します。 まとめると以下のとおりです。
Hibernate Session のスコープ戦略パターン
戦略パターン スコープ 解決する問題 手段
オープン・セッション・イン・ビュー (OSIV) 1リクエスト (Session-per-request) ビューのレンダリングで LazyLoading に関するエラーが出る Spring で用意している SessionInViewFilter クラス
フロー・マネジド・パーシスタンス(FMP) 1カンバセーション(Session-per-conversation) 画面やボタンを跨ぐ一連の処理(長い UnitOfWork)で、Session に手動でドメインオブジェクトを同期しないといけない(e.g. session.reflesh() )。 Spring Web Flow
もし SWF を使わないのなら、 FMP は自分で手動実装することになるでしょう。 また EJBサーバーを用意して JBoss Seam を使う場合なら、FMP同様のことができるかと思います。 つまり SWF を使う場合は、 FMP を使うと良いということになります。 実際の設定方法は次回へ。
T.B.C.

2012年6月12日火曜日

可能性を表す英語の副詞

頻度を示す16個の英語の副詞の使い方を完璧に身につける簡単訓練法 にて、
頻度の副詞が紹介されていましたが、
ここでは、可能性を表す副詞を示します。



可能性 英語の表現
100% definitely
80% probably/likely
60% possibly
50% maybe/perhaps
40% possibly not
20% probably not
0% definitely not

ネイティヴの会話で definitely はよく聞きますよね。
probably は日本語にすると十中八九なので、起きると思うときに使った方がいいと思います。

2012年6月8日金曜日

Gumroad 「出荷情報を必要とする」とは?

Gumroad でのアイテム登録時に、「出荷情報を必要とする」のチェックボックスがありますが、これをチェックすると、ユーザーの購入画面に、住所入力欄が出ます。
単純に、住所を入力させるかどうかの違いですね。
商品を送らないといけないとかそういった場合に使えます。

英語環境だと "requiring shipping information" と表示されます。

2012年6月7日木曜日

Worse is better とは

Worse is better という言葉があります。
Cf. http://en.wikipedia.org/wiki/Worse_is_better

文字通り訳すと「悪い方が良い」。
この撞着語法に、本当に??と思った方には、この言葉の意味を説明します。

Lispの専門家リチャード・ガブリエルのエッセイ『Lisp: 良い知らせと悪い知らせ、そして大勝ちするには』“Lisp: Good News, Bad News, How to Win Big”(1990) に書かれた言葉です(*1)。

「悪い方が良い」をより詳しく言うと、
より悪い機能性の方が、実際に利用するとき、良い選択になる
別の言い方をすると、
ソフトウェアは、制限されていて、シンプルなものが、実際にはよりユーザーや市場に魅力的になる
ということです。

どうでしょうか。"Less is more" も同じようなことですね。
アップルのデザインはこの形をとっていますよね。
みなさんの参考になれば嬉しいです。


References
*1
http://www.dreamsongs.com/WorseIsBetter.html

Scala on VSCode

Scala on VSCode ===================== Docker を利用した VSCode remote development 上で Scala 開発をする方法 Links ========== ## Scala on VSCode remote...