1

6つのプロパティと変更日を持つクラスがあります。

@Entity
@Table(name = "product")
public class Product {

   private Long id;

   private String title; // if changed, update lastChanged

   private String subtitle;

   private Text summary; // if changed, update lastChanged

   private Text description; // if changed, update lastChanged

   private Text otherText;

   private List<Text> reviews; // if changed, update lastChanged

   private Date lastChanged;

   // Getters and setters

}

-

@Entity
@Table(name = "text")
public class Text {

   private Long id;

   private String content;

   private int typeCode;

   // Getters and setters

}

(これは明らかに実際のドメインモデルの大幅に簡略化されたバージョンですが、基本的な問題を示しています)

要件は次のとおりです。「title」、「summary」、「description」、または「reviews」が変更された場合は、「lastChanged」を現在の日付に設定します。
背景:これらのフィールドは外部APIに関連しています。私の顧客は、日付X以降にAPI関連のフィールドに変更が加えられた製品を知りたいと思っています。

HibernateインターセプターとHibernateイベントリスナーを実装することで、要件を満たそうとしました。どちらも私が期待したようには機能しませんでした。たとえば、「summary」を変更すると、Hibernateは次のように通知します。「content」フィールドがテーブル「text」で変更されました。

'summary'、'description'、または'otherText'が変更されたかどうかはまだわからないため、この情報はあまり役に立ちません。したがって、「lastChanged」を更新する必要があるかどうかはわかりません。

私の他のアイデア:

  • 変更されたTextオブジェクトのIDを取得し、SQLを介してそれに接続されている製品を見つけてください。これは適切に機能しますが、これは非常に醜い解決策であり、ドメインモデルでは非常に複雑になります。

  • 変数セッターに更新ロジックを実装します。これに関する2つの問題:Hibernateはデータベースからオブジェクトをロードしているときにセッターを呼び出し(もちろんタイムスタンプの更新につながるべきではありません)、上記の問題を解決しません。'content'のセッターが呼び出されたら、どうしますか?製品のどのプロパティが変更されたかはわかりません。

この問題に対するエレガントな解決策はありますか?

4

1 に答える 1

0

変更通知の問題を一般的な方法で解決することは簡単ではありません。特に、通知を盲目的に送信しないステートフルメカニズムが必要な場合は、インフラストラクチャの特定の部分から発生する変更が通知をトリガーしないようにします。

問題の詳細によっても、問題が単純化または複雑化する可能性があります。たとえば、同じTextオブジェクトをオブジェクトの複数のフィールドから参照できProductますか?Product同じように、異なるオブジェクト間で共有することは可能ですか?これらのいずれかが可能な場合は、共有オブジェクトが変更されたときの適切なアクションの方針を決定する必要があります。たとえば、すべての関係者に通知しますか?

通知インフラストラクチャを構築するための基本的なデザインパターンの1つは、オブザーバーパターンです。このアプローチを使用して、すべてのオブジェクトが参照Productするすべてのオブジェクトの変更を監視するようにすることができTextます。

このアプローチが目的に対して複雑すぎるか遅い場合は、アーキテクチャを再考することをお勧めします。たとえば、Textクラスを不変にすることは理にかなっていますか?または、各オブジェクトが他の1つのオブジェクトによってのみ参照されている場合、適切なコンストラクターとともに、その親オブジェクトを指すTextフィールドを追加することは可能でしょうか。Text

偽の通知を回避することに関しては、いくつかの潜在的な解決策があります。

  • セッターへのアクセスを制限して、永続化/シリアル化メカニズムで使用できるように予約し、システムの残りの部分で異なるメソッドのセットを使用します。たとえば、次のようなことができます。

    public class Text {long privateId; ... private setPrivateId(long x){privateId = x; }

    public setId(long x) {
       setPrivateId(x);
    
       this.triggerChangeNotifiers();
    }
    ...
    

    }

  • セッターを経由せずに、Hibernateにフィールドに直接入力してもらいます。そのための注釈はたくさんあると思いますが、このアプローチでは将来のリファクタリングがはるかに難しくなる可能性があることに注意してください。

于 2012-11-15T13:46:48.110 に答える