休止状態の永続性マッピングでFlyweightオブジェクトを使用する方法はありますか?私のデータモデルには、同じになる多くのオブジェクトが含まれています。同じオブジェクトごとに個別のインスタンスを作成する代わりに、Flyweightデザインパターンを使用して、常に同じ物理オブジェクトを参照したいと思います。休止状態でこれを達成する方法は?
ところで。すべてのJVMは、同じ文字列が複数回使用されたときに常に同じ物理インスタンスになるように、文字列の使用を最適化しますか?
休止状態の永続性マッピングでFlyweightオブジェクトを使用する方法はありますか?私のデータモデルには、同じになる多くのオブジェクトが含まれています。同じオブジェクトごとに個別のインスタンスを作成する代わりに、Flyweightデザインパターンを使用して、常に同じ物理オブジェクトを参照したいと思います。休止状態でこれを達成する方法は?
ところで。すべてのJVMは、同じ文字列が複数回使用されたときに常に同じ物理インスタンスになるように、文字列の使用を最適化しますか?
場合によります。
読み取り専用値の場合、毎回新しいインスタンスではなくプールからオブジェクトを返すカスタム UserType を作成することで、flyweight パターンを簡単に実装できます。
エンティティの場合、Hibernate はデフォルトで正気であり、トランザクション間で一貫性を保ちたいため、データの競合状態を回避するためにセッション間でエンティティを共有しません。それはあなたが望んでいることではないと思います。
しかし、そうである場合 (実際に何をしているのかを知らずにこれを行うことはまったく推奨されません) は、第 2 レベルのキャッシングを目的とした Interceptor.getEntity() を実装できます。そのメソッドでは、エンティティ (他のセッションで共有されているものも含む) を返すことができ、エンティティのフライウェイト パターンを効果的に持つことができます。
しかし、データの一貫性のためにこれを強くお勧めします-実際のエンティティを試してフライウェイトするよりも、エンティティによって参照される実際の不変のフライウェイト値を使用する方がはるかに優れています。
はい、Hibernate で Flyweight パターンを実装できます。
flyweight パターンは、インスタンスごとのメモリ使用量を最小限に抑える方法です。戦略は、flyweight インスタンス間でできるだけ多くの状態を共有することです。あなたの場合、共有可能な状態は、休止状態のオブジェクト識別子と、オブジェクトのアイデンティティを維持するための追加の状態を除くすべてです。
各 flyweight インスタンスには、独自のオブジェクト IDが必要です。追加の状態は、共通の状態を共有するオブジェクトを区別するための ID を実装する方法です。
public boolean equals(Object obj){
Fly other; [..]//check type
//null checks ommitted
return other.myState.equals(myState) && other.commonState.equals(commonState);
}
オブジェクト ID がインスタンス間で共有されている場合、hibernate はすべての物理インスタンス (参照) を同じインスタンスとして解釈します。Hibernate は equals メソッドを使用してオブジェクトの同一性をチェックしますが、あなたの equals 実装(! a.equals(a) == true)
は不正なものを返す必要があります。Equalは再帰的でなければなりません。このコントラクトを破ると、コントラクトに依存するすべてのライブラリが壊れます (コレクション、休止状態など)。
オブジェクトを区別するためにhibernate オブジェクト識別子を使用して equal メソッドを実装することはできません。これにより、オブジェクト ID が永続状態 (永続または一時) に依存するようになります。
Hibernate で共通の状態をモデル化する 1 つの方法は、共有状態オブジェクトと flyweight オブジェクトの間の 1 対多の関連付けです。(2 つのテーブルを結合せずにデータをマッピングする方法を誰かが考えているのではないでしょうか?)
文字列:内部化された文字列のみが共有されます。ほとんどの場合、これは最善の解決策ではありません。シンボル(クラス名、メソッド名など)に適しています。内部化された文字列はガベージ コレクションによって収集されることはなく、とにかくガベージ コレクションされる String インスタンスが必要ですnew String("..").intern()
。割り当ては保存されません。ベース文字列が gc 生成に耐えられないか、スタックに割り当てられる可能性があるという小さな利点しかありません (ホット スポットでのエスケープ解析が有効で適用可能な場合)。
すべての JVM は、同じ文字列が複数回使用された場合に常に同じ物理インスタンスになるように、文字列の使用を最適化しますか?
私はそれを非常に疑っています。同じクラスファイルで、次のように定義すると:
String s1 = "Yes";
String s2 = "Yes";
おそらくs1 == s1になるでしょう。
しかし、あなたが好きなら:
String x = loadTextFromFile(); // file contains es
StringBuilder b = new StringBuilder();
s2 = b.append("Y").append(x).toString(); // s2 = "Yes"
ランタイムがロードされたすべての文字列をチェックして、それらのビルダーの戻り値と比較するとは思いません。
そのため、常に equals() を使用してオブジェクトを比較します。すべての適切なイコールは次で始まるため、とにかく良いアドバイスです。
if (this == o) {
return true;
}
オブジェクトがIDによる同等性を実装している場合、Hibernateはその主キーに関連付けられた単一のインスタンスのみを持ちます。Flyweightとまったく同じアイデアだとは思いませんが、重要なのは、同じHibernateオブジェクトのインスタンスが多くないということです。