0

アプリにリビジョン履歴を追加していますが、履歴オブジェクトにアーカイブ ドキュメントを埋め込む際に問題が発生しています。私たちの状態は次のようになります。

@ToString
@EqualsAndHashCode
@Entity("bookOrder")
@Converters({DateTimeConverter.class, LocalDateConverter.class})
public class BookOrderState {
    @Id
    @Getter
    private Long id;

    @Indexed
    @Getter
    private final BookOrderStatus status;

    @Getter private Long version;
...

履歴オブジェクトは次のようになります。

@ToString
@Entity("bookOrderHistory")
@Converters(DateTimeConverter.class)
public class BookOrderStateHistory {

    @Id
    @Getter
    private String id;

    @Getter
    private DateTime createdDate;

    @Getter
    private BookOrderState bookOrder;
...

注文を更新すると、データベースから現在の状態を取得し、独自の ID とタイムスタンプを取得する履歴オブジェクトにラップし、新規bookOrderStateHistoryと更新の両方bookOrderStateをデータベースに保存します。このプロセスは正しく書き込みますが、取得すると、すべて同じ を持つ複数の一意の履歴オブジェクトになりますbookOrderState@IdこれをBookOrderStateまでたどりました。多くの履歴オブジェクトは同じ状態オブジェクトを持つため_id(ただし、オブジェクトの実際の状態には違いがあります)、モーフィアはそれらがすべて同じ状態オブジェクトを取得する必要があると想定しているように見えます。_id埋め込まれた状態オブジェクトをインターセプトし、書き込み時のみに切り替えるid方法 (読み取り時はその逆) を一緒にハックしましたが、これは間違っているように感じます。

Tl;dr:id -> _idオブジェクトが別のドキュメント内にある場合に、モルフィアがオブジェクトを 'ing しないようにする簡単な方法はありますか?

4

1 に答える 1

1

私はMorphiaを使用してほぼ同じことを行っており、問題は発生していません。上記のコードには表示されませんが、「bookOrder」属性に@Referenceの注釈が付けられている場合は、説明している動作が表示されます。@Referenceを入れないと、Morphiaはデフォルトで@Embeddedになっているようですので、大丈夫です。
オブジェクトの履歴を保存するために使用する「Snapshot」という単純なクラスがあります。

@Entity("snapshots")
public class Snapshot<T>
{
  @Id
  protected ObjectId id;

  @Embedded
  protected T data;
}

オブジェクトが変更されるたびに、そのスナップショットを作成し、そのスナップショットをデータベースに保存します。次の簡単なテストケースを使用すると、正しい動作が得られるようです。

Point pt = new Point();
pt.setLatitude( 40.0 );
pt.setLongitude( 40.0 );

ds.save( pt ); //ds is Datastore

Snapshot<Point> ts1 = new Snapshot<Point>();
ts1.setData( pt );
ds.save( ts1 );

pt.setLatitude( 50.0 );
ds.save( pt );

pt = ds.get( Point.class, pt.getId() );

Snapshot<Point> ts2 = new Snapshot<Point>();
ts2.setData( pt );

ds.save( ts2 );

ts1 = ds.get( Snapshot.class, ts1.getId() );
ts2 = ds.get( Snapshot.class, ts2.getId() );

Assert.assertEquals( 40.0, ts1.getData().getLatitude() );
Assert.assertEquals( 50.0, ts2.getData().getLatitude() );

Assert.assertEquals( 40.0, ts1.getData().getLongitude() );
Assert.assertEquals( 40.0, ts2.getData().getLongitude() );

両方のスナップショットのポイントのObjectIdは元のPointオブジェクトと同じですが、「ts2」のポイントの緯度は50.0で、「ts1」のポイントの緯度は40.0です。ObjectId値は、オブジェクトがデータベースに挿入されたときに割り当てられ、変更されることはありません(http://www.mongodb.org/display/DOCS/Object+IDs)。

申し訳ありませんが、あなたの問題が正確に何であるかはわかりませんが、私が非常によく似た何かをしていて、それが機能しているように見えることをお知らせしたいと思います。たぶん、BookOrderStateHistoryの「bookOrder」に@Embeddedアノテーションを追加してみてください。

幸運を!

于 2012-08-14T02:28:29.410 に答える