gpt4 book ai didi

java - 为什么 mongodb 似乎保存了一些二进制对象而不保存其他对象?

转载 作者:IT老高 更新时间:2023-10-28 13:23:16 26 4
gpt4 key购买 nike

我不确定从哪里开始或有哪些相关信息,请告诉我哪些附加信息可能有助于解决此问题。

我正在开发一个简单的 cometd 应用程序,并且我使用 mongodb 作为我的存储后端。当应用程序启动时,我获得了一个 mongodb 实例,并将该实例用于所有查询。这实际上是由 mongo java 驱动程序文档推荐的,如下所述:http://www.mongodb.org/display/DOCS/Java+Driver+Concurrency .我捕获了稻草,认为这个问题与线程安全有关,但根据该链接,mongodb 是完全线程安全的。

这就是有趣的地方。我有一个扩展 BasicDBObject 的类.

public class MyBasicDBObject {

private static final String MAP = "map";

public boolean updateMapAnd(String submap, String key, byte[] value) {
Map topMap = (Map)this.get(MAP);
Map embeddedMap = topMap.get(submap);
byte[] oldValue = embeddedMap.get(key);

newValue = UtilityClass.binaryAnd(oldValue, value);

embeddedMap.put(key, newValue);
topMap.put(submap, embeddedMap);
this.put(MAP, topMap);
}

public boolean updateMapXor(String submap, String key, byte[] value) {
Map topMap = (Map)this.get(MAP);
Map embeddedMap = topMap.get(submap);
byte[] oldValue = embeddedMap.get(key);

newValue = UtilityClass.binaryXor(oldValue, value);

embeddedMap.put(key, newValue);
topMap.put(submap, embeddedMap);
this.put(MAP, topMap);
}
}

接下来的两个骨架类扩展 MyBasicDBObject .

public class FirstDBObject extends MyBasicDBObject { //no code }

public class SecondDBObject extends MyBasicDBObject { //no code }

我以这种方式设置类的唯一原因是为了提高代码在同一范围内处理这两个对象时的可读性。这让我可以执行以下操作...

//a cometd service callback
public void updateMapObjectsFoo(ServerSession remote, Message message) {

//locate the objects to update...
FirstDBObject first = (FirstDBObject) firstCollection.findOne({ ... });
SecondDBObject second = (SecondDBObject) secondCollection.findOne({ ... });

//update them as follows
first.updateMapAnd("default", "someKey1", newBinaryData1);
second.updateMapAnd("default", "someKey2", newBinaryData2);

//save (update) them to their respective collections
firstCollection.save(first);
secondCollection.save(second);
}

public void updateMapObjectsBar(ServerSession remote, Message message) {

//locate the objects to update...
FirstDBObject first = (FirstDBObject) firstCollection.findOne({ ... });
SecondDBObject second = (SecondDBObject) secondCollection.findOne({ ... });

/**
* the only difference is these two calls
*/
first.updateMapXor("default", "someKey1", newBinaryData1);
second.updateMapXor("default", "someKey2", newBinaryData2);

//save (update) them to their respective collections
firstCollection.save(first);
secondCollection.save(second);
}

UtilityClass完全按照方法命名,按位 &和按位 ^通过迭代传递的字节数组。

这是我完全迷失的地方。 updateMapObjectsFoo()完全按预期工作,firstsecond反射(reflect)数据库中的变化。 updateMapObjectsBar()另一方面,只能设法正确更新 first .

调试检查updateMapObjectsBar()表明二进制对象实际上在两个对象上都正确更新了,但是当我前往 mongo shell 调查问题时,我看到 first在数据库中更新,second不是。我从哪里得到线程安全与它有关的想法?唯一让我烦恼的是 secondCollection由其他 cometd 服务使用,而 firstCollection不是。一方面这似乎相关,但另一方面,因为 Foo作品和Bar没有。

我已将代码拆开并重新组合在一起,但我不断地回到同样的问题。这到底是怎么回事?

似乎我遗漏了最相关的部分,即 java 泛型的噩梦以及 mongodb 驱动程序对该语言的这一特性的依赖。 BasicDBObject本质上是 Map<String, Object> 的包装器.问题是,一旦您在该 map 中存储了一个对象,您必须将其转换回您将其放入其中时的状态。是的,这可能看起来很明显,在发布这个问题之前我就很清楚了。

我无法确定到底发生了什么,但我会向 java + mongodb 用户提供这个建议。您将进行大量转换,并且您的数据结构越复杂,您需要的转换就越多。长话短说,不要这样做:

DBObject obj = (DBObject) collection.findOne(new BasicDBObject("_id", new ObjectId((String)anotherObj.get("objId"))));

当你在做快速原型(prototype)时,一个衬线很诱人,但当你开始一遍又一遍地做这件事时,你肯定会犯错误。现在写更多代码,以后少受挫折:

DBObject query = new DBObject();
String objId = (String) anotherObj.get("objId");
query.put("_id", new ObjectId(objId));
obj = (DBObject) collection.findOne(query);

我认为这很烦人,但我应该期望直接与 Mongo 进行交互,而不是使用某种库来让我的生活更轻松。我在这件事上自欺欺人了,但希望有人能从我的错误中吸取教训,为自己省去很多挫折。

感谢大家的帮助。

最佳答案

这很容易成为多线程问题。如果只有一个 Mongo 实例,您认为 Mongo、DB 和 DBCollection 对象是线程安全的是正确的,但 DBObjects 不是线程安全的。但即使它们是线程安全的,您的 updateMapObjectsFoo/Bar 方法也无法确保它们是数据库上的原子操作。

不幸的是,您需要对代码进行的更改比仅仅散布一些“同步”关键字更加激烈。看看有没有http://www.mongodb.org/display/DOCS/Atomic+Operations不能帮助您了解问题的范围和一些潜在的解决方案。

关于java - 为什么 mongodb 似乎保存了一些二进制对象而不保存其他对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12256005/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com