Как MongoClient :: save (...) может изменить поле _id параметра документа - PullRequest
0 голосов
/ 27 мая 2019

У меня есть класс 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 предполагает, что идентификатор не изменяется, т. Е. Строка 5ceb8ebb9790855fad9be2fc не изменится.Есть ли у нас гарантия на это?

Q2 : Как правильно реализовать saveUser() правильно?

РЕДАКТИРОВАТЬ :Конфигурация JSON объекта пользователя для создания MongoClient выглядит следующим образом (на случай, если что-то не так):

"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
}
...