在morphia中使用@Id嵌入对象

时间:2012-08-13 20:07:28

标签: java mongodb morphia

我们正在向我们的应用添加修订历史记录,并且我们在将历史记录对象中嵌入档案文档时遇到了一些问题。我们的州看起来像这样:

@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;
...

当我们更新订单时,我们从db中获取其当前状态将其包装在历史对象中,该对象获取自己的id和时间戳并将新的bookOrderStateHistory和更新的bookOrderState保存到db 。此过程正确写入,但在检索时,我们最终得到的多个唯一历史对象都具有相同的bookOrderState。我们将其追溯到BookOrderState上的@Id。由于许多历史对象将具有相同_id的状态对象(但在对象的实际状态中存在差异),因此morphia似乎假设它们都应该获得相同的状态对象。我们一起攻击了一种拦截嵌入式状态对象的方法,并在写入时将_id切换为id(与读取方式相反),但这感觉不对。

Tl;博士:是否有一种简单的方法可以防止id -> _id对象在另一个文档中出现时出现吗?

1 个答案:

答案 0 :(得分: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() );

两个快照中的点与原始Point对象具有相同的ObjectId,但“ts2”中的Point的纬度为50.0,而“ts1”中的Point的纬度为40.0。 ObjectId值在对象插入数据库时​​分配,永远不会更改(http://www.mongodb.org/display/DOCS/Object+IDs)。

抱歉,我不确定你的问题究竟是什么,但是想让你知道我正在做一些非常相似的事情,它似乎正在发挥作用。也许尝试在BookOrderStateHistory中将@Embedded注释添加到“bookOrder”?

祝你好运!