MongoClient :: save(...)如何更改文档参数的_id字段

时间:2019-05-27 08:54:28

标签: vert.x mongodb-java

我有一个User类,它嵌入一个JsonObject来表示用户的字段。这个类看起来像这样:

class User {
  private JsonObject data;

  public User(...) { 
    data = new JsonObject();
    data.put("...", ...).put(..., ...);
  }

  public String getID() { return data.getString("_id"); }

  // more getters, setters

  // DB access methods
  public static userSave(MongoClient mc, User user){
    // some house keeping
    mc.save("users", user.jsonObject(), ar -> {
      if(ar.succeeded()) { ... } else { ... }
    });
  }


}

我花了超过半天的时间来弄清楚为什么有时user.getID()的调用会产生以下错误:ClassCastException: class io.vertx.core.json.JsonObject cannot be cast to class java.lang.CharSequence。我缩小到userSave()方法的范围,更具体地说,缩小到MongoClient::save(),它实际上产生了一种副作用,该副作用将data._id从类似

"_id" : "5ceb8ebb9790855fad9be2fc"

变成类似

"_id" : { 
  "$oid" : "5ceb8ebb9790855fad9be2fc"
}

这由vertx文档确认,该文档指出“ 此操作可能会更改文档参数的_id字段”。实际上,对于其他写入方法(例如插入)也是如此。

我提供了两种解决方案,并且在保持save()字段为最新状态的同时正确完成_id的问题很少。

S1 一种实现方法是保存Json对象的副本,而不是对象本身,即mc.save("users", user.jsonObject().copy(), ar -> {...});。从长远来看,这可能会很昂贵。

S2 另一种方法是“记住” _id,然后将其重新插入data部分的if(ar.succeeded()) {data.put("_id", oidValue); ...}对象中。但是由于我们是异步的,所以我认为save()data.put(...)之间的间隔不是原子的吗?

Q1 :解决方案 S1 假定ID不变,即字符串5ceb8ebb9790855fad9be2fc不变。我们对此有保证吗?

第二季度:正确实施saveUser()的正确方法是什么?

编辑:用于创建MongoClient的配置JSON对象用户如下(以防万一):

"main_pool" : {
        "pool_name"         : "mongodb",
        "host"              : "localhost",
        "port"              : 27017,
        "db_name"           : "appdb",
        "username"          : "xxxxxxxxx",
        "password"          : "xxxxxxxxx",
        "authSource"        : "admin",
        "maxPoolSize"       : 5,
        "minPoolSize"       : 1,
        "useObjectId"       : true,
        "connectTimeoutMS"  : 5000,
        "socketTimeoutMS"   : 5000,
        "serverSelectionTimeoutMS" : 5000
}

0 个答案:

没有答案