У меня есть класс 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
}