java - 吗啡中带有 @Id 的嵌入对象

标签 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;
...

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

Tl;dr:是否有一种简单的方法可以防止吗啡在另一个文档中时对对象进行 id -> _id 处理?

最佳答案

我正在使用 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 与原始 Point 对象具有相同的 ObjectId,但“ts2”中的 Point 的纬度为 50.0,而“ts1”中的 Point 的纬度为 40.0。 ObjectId 值在对象插入数据库时​​分配,并且永远不会更改 (http://www.mongodb.org/display/DOCS/Object+IDs)。

抱歉,我不确定您的问题到底是什么,但想让您知道我正在做一些非常类似的事情,而且似乎有效。也许尝试将 @Embedded 注释添加到 BookOrderStateHistory 中的“bookOrder”?

祝你好运!

关于java - 吗啡中带有 @Id 的嵌入对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11941498/

相关文章:

java - 如何使用 Java 中的 Morphia 和 Play 框架从实体中检索特定字段

java - 基于深度嵌套对象单字段的morphia查询

java - react native - 错误 : method does not override or implement a method from a supertype

mysql - 为什么 Mongodb 优于 MySql 用于 NodeJs 开发?

node.js - 如何重试mongodb事务?

javascript - MongoDB with Mongoose - 仅查找某些子文档

java - 如何将对象从ArrayList传输到LinkedList

java - 在 JBoss 5.0.x 中创建单个 jbossall-client.jar 包?

java - 使用 Java 8 Lambda 表达式将字符串数组转换为 Map

java - MongoDb 分片和字符串 id