MongoDB:尝试从JSON中读取Long类型导致java.lang.Integer无法转换为java.lang.Long。

5
我有一段代码可以从MongoDB中以特定格式读取数据,需要进行测试。
为了进行测试,我创建了一个JSON文件,用于测试数据。
{
  "id": ObjectId("57552e32e4b0839ede67e0af"),
  "serial" : 574000690,
  "startDate" : ISODate("2016-08-22T23:01:56.000Z"),
  "endDate" : ISODate("2016-10-22T22:01:56.000Z"),
  "reason": ""
}

这是应该被创建的对象:
public static class MyObject implements Serializable{
    private String id;
    private long serial;
    private Date startDate;
    private Date endDate;
    private String reason;
}

我有一段代码,它可以读取一个JSON文件并创建一个Mongo文档,并将其写入数据库:
List<Document> docs = dirAsDbObjects(dir + File.separator + 
subDir.getName()).collect(Collectors.toList());

docs.forEach(docManipulator);
docs.forEach(doc -> doc.putIfAbsent("_id", new ObjectId()));

ret.addAll(docs);

MongoDatabase db = mongoClient.getDatabase(dbName);
MongoCollection<Document> coll = db.getCollection(subDir.getName());

List<InsertOneModel<Document>> inserts = docs.stream().map(InsertOneModel::new).collect(Collectors.toList());
coll.bulkWrite(inserts);

一旦数据被写入,就有一段代码尝试从MongoDB中读取数据并将其填充到一个MyObject实例中:
    public MyObject(Document doc) {
        id = doc.getObjectId(DBConstants.ID).toString();
        serial = doc.getLong(DBConstants.SERIAL);
        startDate = doc.getDate("startDate");
        reason = doc.getString("source");
    }

这句话的意思是“出现错误信息导致失败”。
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long

由于这行代码 serial = doc.getLong(DBConstants.SERIAL);,它基本上从我的JSON中获取数字作为“Integer”,因此无法将其读取为长整型。
我尝试了以下代码,并且它可以工作:
Long.parseLong(doc.get(DBConstants.SERIAL).toString())

但是这是最好的解决方案吗?.toString() 总是会得到一个数字的字符串表示吗?有没有一种方法可以在 JSON 中保留一个数字,使其被读取为 Long
更新:
@glytching 给出了一个很好的答案!
我还发现另一种方法,显然如果你将 JSON 的数字元素包装在 NumberLong 中,当从 Mongo 文档翻译时它将被解析为 Long
所以使用旧代码,我可以通过更改我的 JSON 来使它工作:
{
  "id": ObjectId("57552e32e4b0839ede67e0af"),
  "serial" : NumberLong(574000690),
  "startDate" : ISODate("2016-08-22T23:01:56.000Z"),
  "endDate" : ISODate("2016-10-22T22:01:56.000Z"),
  "reason": ""
}
1个回答

9
Mongo Java驱动程序确定serial的值可以“适合”INT32,因此将其视为INT32处理。当您调用doc.getLong()时,您要求驱动程序将其整数强制转换为长整型,因此出现了类转换异常。例如,如果serial的值为2147483648(即最大整数值+1),则Mongo Java驱动程序将认为它是INT64,然后您可以安全地调用doc.getLong()
因此,由于(a)您在类模型中对该属性建模为Long,并且(b)不是该属性的每个持久化值都需要存储为INT64… 当将其转换为Long时,必须注意其持久化类型。
怎么做?好吧,只要serial属性以某种数字形式(例如INT32INT64)持久化,那么这个调用…
doc.get(DBConstants.SERIAL)

...总是返回一个java.lang.Number的子类对象,因此将其转换为Number并使用longValue()将起作用。

例如:

serial = ((Number) doc.get(DBConstants.SERIAL)).longValue()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接