2011-01-13 7 views
6

私が開発しようとしているアプリケーションでは、Hibernateをデータベースからメモリにたくさんの永続オブジェクトを取得するために排他的に使用しています。アプリケーションは、このインメモリスナップショットをデータベースから毎回更新し、それがデータベースとの唯一の通信である必要があります。Hibernateマップセットを変更不可能なセットとしてロードするにはどうしたらいいですか?

メモリ内のオブジェクトは、一連の計算に使用されます。計算でこれらのオブジェクトを変更してはいけません。何らかのクラスを間違ってやったことを除いて、私はバグを狩る日を過ごさなければならなかった。今私はオブジェクトツリー全体を不変にする最良の方法が何であるか疑問に思っています。熱心にすべてのエンティティとコレクションをマークし、すべてのエンティティとコレクション

  • をフェッチ

    • :私はしてデータベースにアクセスするクライアントを妨げてきた

      public class Building { // persistent entity 
          private String name; // hibernate-mapped property 
          private Set<Person> inhabitants; // hibernate-mapped collection 
      
          // getters 
      } 
      
      public class Person { // persistent entity 
          private String name; // hibernate-mapped property 
      
          // getters 
      } 
      

      は、クラス階層は次のようになりますと仮定しますHibernateマッピングでmutable=falseを使用している場合

    • Hibernateセッションのインスタンスを提供していないか、またはstate-changin g DAOメソッド。

    ここで私が避けたいエラーは、誤ってbuilding.getInhabitants().clear();に行くことです。そして、それを返す、Collections.unmodifiableSet()コールにgetInhabitants最初のラップinhabitantsを行います

    1. ゲッターはをラップ:私は、これらのオプションを考えることができます。

      • 長所:最小仕事、少なくとも余分なコード
      • 短所:BuildingMutableBuildingからPersonMutablePersonに名前を変更し、不変クラスBuildingPersonを提供:ハック
    2. ラッパークラスが感じます。私のアプリケーションは明確なスナップショットポイントを持っているので、(私が今行っているように)変更可能なオブジェクトとしてレコードをフェッチし、深く不変なコピーを作成し、そのオブジェクトツリーをクライアントに提示することができます。

      • 長所:ストレートjava、休止状態の魔法。私は私の好きなキーワードを使用するようになる:final
      • 短所:より多くのコードを書いて維持する。また、Hibernateは変更可能なインスタンスをメモリに保持しますか?
    3. Hibernateマッピング魔法は:1つの魔法のキーワードはCollections.unmodifiableSet()または同等で私のエンティティオブジェクトのそれはセットのコレクションをラップするために休止状態を指示することを使用します。(注:私は、XMLマッピングファイルを使用します)

      • 長所:エレガント、余分なコード
      • 短所:1つのHibernateの延長という用途:このようなキーワードは
    4. Hibernateの拡張存在しないかもしれないが私自身のオブジェクトインスタンシエータを書くことを指し、それを返す前にCollections.unmodifiableSet()にセットをラップします。

      • 長所:このような拡張ポイント

    存在しないかもしれない今、私は私がいない主な理由は、#2の方に傾いています:

  • 短所が私のゲッターをハッキングよりもエレガント3と4が可能かどうかを知る。

    どのような方法が最適ですか?

  • 答えて

    6

    オプション1、確かです。それは "ハッキー"ではない、そして、それはちょうどあなたがプロパティへのアクセスを抽象化した理由です:-)「メソッド」ではなくHibernateで「フィールドアクセス」を使用する必要があることに注意してください。 Hibernateに変更不可能なコレクションを提供するリスク。

    残念ながら、Hibernateは変更不可能なコレクションを配置する方法を提供していませんが、@PostLoadイベントリスナーを使用して、オブジェクトがロードされるとすべてのコレクションを変更できると思います。

    +0

    私がゲッターとセッターを書く理由を思い出させるために+1: – KarlP

    +0

    これは最善の解決策のようです。私は、変わるクラスがときどき大丈夫だという事実を条件にしなければならないでしょう! :) – oksayt

    関連する問題