当同时创建两个相互引用的对象时,为什么第一个对象的ObjectId在存储到MongoDB后会发生变化?

发布于 2024-12-18 13:27:38 字数 1972 浏览 3 评论 0原文

我使用的是spring roo,但我认为这不是spring roo问题而是MongoDB问题。

我有两个相互引用的类(文档)。

public class Dummy {
    private String dummyString;

    @DBRef
    private Dummy2 dummy2;
}

public class Dummy2 {
    private String dummyString;
    private ObjectId dummyId;
}

“Dummy”通过引用引用“Dummy2”。
由于技术原因,“Dummy2”通过手动存储ObjectId来引用“Dummy”。

这是我创建两个对象的集成测试。

@Test
public void testDummyWithDummy2() {
    DummyDataOnDemand dod = new DummyDataOnDemand();
    Dummy dummy = dod.getNewTransientDummy(0);
    dummyService.saveDummy(dummy);

    Dummy2DataOnDemand dod2 = new Dummy2DataOnDemand();
    Dummy2 dummy2 = dod2.getNewTransientDummy2(0);
    dummy2.setDummyId(dummy.getId());
    dummy2Service.saveDummy2(dummy2);

    dummy.setDummy2(dummy2);
    dummyService.updateDummy(dummy);
}

我发现结果不一致。
目前有两种情况。

  1. 它工作正常。他们按预期互相引用。

    虚拟:

    <前><代码>{ "_id": ObjectId("4ecfa5429418d09a94f1c8ae"), "_class": "com.mytest.model.Dummy", "虚拟字符串": "虚拟字符串_0", “虚拟2”:{ "$ref": "虚拟2", "$id": ObjectId("4ecfa5429418d09a94f1c8af") } }


    虚拟2:

    <前><代码>{ "_id": ObjectId("4ecfa5429418d09a94f1c8af"), "_class": "com.mytest.model.Dummy2", "虚拟字符串": "虚拟字符串_0", “dummyId”:ObjectId(“4ecfa5429418d09a94f1c8ae”) }
  2. 有时,dummy 不指代任何内容,而 dummy2 指代无效的 ObjectId。

    虚拟:

    <前><代码>{ "_id": ObjectId("4ecfa039941836a18fe88b24"), "_class": "com.mytest.model.Dummy", “虚拟字符串”:“虚拟字符串_2147483647” }


    虚拟2:

    <前><代码>{ "_id": ObjectId("4ecfa039941836a18fe88b23"), "_class": "com.mytest.model.Dummy2", "虚拟字符串": "虚拟字符串_0", “dummyId”:ObjectId(“4ecfa039941836a18fe88b22”) }

我想知道为什么会出现后一种结果。看来Dummy 和Dummy2 指的不太一样,看起来像是新创建的。但是带有 ObjectId("4ecfa039941836a18fe88b22") 的虚拟对象在哪里?是不是丢了?为什么?

Roo:1.2.0.M1 [修订版 1fa252f]
MongoDB:2.0.1

I am using spring roo, but I think this is not a spring roo issue but the MongoDB issue.

I have two classes (documents) referring to each other.

public class Dummy {
    private String dummyString;

    @DBRef
    private Dummy2 dummy2;
}

public class Dummy2 {
    private String dummyString;
    private ObjectId dummyId;
}

'Dummy' refers to 'Dummy2' by reference.
'Dummy2' refers to 'Dummy' by storing ObjectId manually due to technical reasons.

Here is my integration test creating two objects.

@Test
public void testDummyWithDummy2() {
    DummyDataOnDemand dod = new DummyDataOnDemand();
    Dummy dummy = dod.getNewTransientDummy(0);
    dummyService.saveDummy(dummy);

    Dummy2DataOnDemand dod2 = new Dummy2DataOnDemand();
    Dummy2 dummy2 = dod2.getNewTransientDummy2(0);
    dummy2.setDummyId(dummy.getId());
    dummy2Service.saveDummy2(dummy2);

    dummy.setDummy2(dummy2);
    dummyService.updateDummy(dummy);
}

I found that the results are inconsistencies.
There are two situations so far.

  1. It works correctly. They refer to each other as expected.

    Dummy:

    {
        "_id": ObjectId("4ecfa5429418d09a94f1c8ae"),
        "_class": "com.mytest.model.Dummy",
        "dummyString": "dummyString_0",
        "dummy2": {
            "$ref": "dummy2",
            "$id": ObjectId("4ecfa5429418d09a94f1c8af") 
        } 
    }
    

    Dummy2:

    {
        "_id": ObjectId("4ecfa5429418d09a94f1c8af"),
        "_class": "com.mytest.model.Dummy2",
        "dummyString": "dummyString_0",
        "dummyId": ObjectId("4ecfa5429418d09a94f1c8ae") 
    }
    
  2. Sometimes, dummy refers to nothing and dummy2 refers to invalid ObjectId.

    Dummy:

    {
        "_id": ObjectId("4ecfa039941836a18fe88b24"),
        "_class": "com.mytest.model.Dummy",
        "dummyString": "dummyString_2147483647" 
    }
    

    Dummy2:

    {
        "_id": ObjectId("4ecfa039941836a18fe88b23"),
        "_class": "com.mytest.model.Dummy2",
        "dummyString": "dummyString_0",
        "dummyId": ObjectId("4ecfa039941836a18fe88b22") 
    }
    

I wonder why the latter result could be happened. It seems that the Dummy is not the same that Dummy2 is referring to, look like the newly created one. But where is the Dummy with ObjectId("4ecfa039941836a18fe88b22")? Is it lost? Why?

Roo: 1.2.0.M1 [rev 1fa252f]
MongoDB: 2.0.1

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小女人ら 2024-12-25 13:27:38

你是如何注意到坏物体的?是通过事后查询集合吗?
另外,你是如何插入对象的,你是否进行了大批量操作?

重要的是要理解,默认情况下 mongodb 的写入不会被确认。
可能会出现错误(dup key,或只是套接字缓冲),并且您的应用程序不会收到异常或收到延迟的异常。
确保使用 SAFE 写入(使用 WriteConcern),然后再次测试并观察是否有任何异常。

how did you notice the bad objects? Was it by querying the collection afterwards?
Also, how did you insert the objects, did you do a large bulk operation?

It is important to understand that by default the writes with mongodb are not acknowledged.
There can be an error (dup key, or just socket buffering) and you application will not get an exception or get a delayed one.
Make sure you use SAFE writes (using WriteConcern) then do you test again and watch for any exception.

妞丶爷亲个 2024-12-25 13:27:38

做了更多测试并查阅了 MongoDB 日志后。我发现这是因为 Spring Roo 生成的集成测试包括一些获取随机文档进行处理的测试。这就是为什么我的集成测试结果不一致的原因。

因此,我会将自己的测试与 Roo 生成的测试分开,以保留 MongoDB 上的预期结果。

After done more tests and consulted the MongoDB log. I found that because the Spring Roo's generated integration tests include some tests that get a random document to process. That's why the results of my integration test are inconsistency.

So I would separate my own tests from the Roo's generated tests to preserve the expected results on MongoDB.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文