如何在Firestore单文档中批量写入多个自定义类对象?
解决Firestore批量写入同一文档合并多个自定义类的问题
问题原因
你之前的批量写法失效,核心原因是Firestore的WriteBatch中,针对同一文档的多次set(merge())操作会被最后一次覆盖。批量处理时,Firestore会按顺序执行操作,但同一文档的多次set只会保留最后一次的结果,所以只有最后一个对象的字段被写入。
可行解决方案
以下几种方法都能实现单次写入合并多个自定义类的效果,且仅算1次数据库写入:
方法1:合并所有对象为一个Map后写入
把每个自定义类转换成Map,合并所有键值对后,用一次set(merge())写入:
K1 k1 = new K1(...); K2 k2 = new K2(...); K3 k3 = new K3(...); // 利用Gson将对象转成Map(也可以手动映射字段) Gson gson = new Gson(); Map<String, Object> k1Map = gson.fromJson(gson.toJson(k1), new TypeToken<Map<String, Object>>(){}.getType()); Map<String, Object> k2Map = gson.fromJson(gson.toJson(k2), new TypeToken<Map<String, Object>>(){}.getType()); Map<String, Object> k3Map = gson.fromJson(gson.toJson(k3), new TypeToken<Map<String, Object>>(){}.getType()); // 合并所有Map(注意字段名重复会覆盖,比如K2和K3的fA) Map<String, Object> combinedData = new HashMap<>(); combinedData.putAll(k1Map); combinedData.putAll(k2Map); combinedData.putAll(k3Map); // 批量写入一次 WriteBatch writeBatch = db.batch(); writeBatch.set(documentReference, combinedData, SetOptions.merge()); writeBatch.commit();
方法2:创建复合POJO类统一管理所有字段
如果字段名无冲突,可以创建一个包含所有类字段的复合类,赋值后单次写入:
// 复合类包含所有需要的字段(注意处理K2和K3的fA字段冲突,比如重命名K3的fA为fAString) class CombinedData { int A; int B; boolean fA; boolean fB; boolean fC; String fAString; } // 赋值 CombinedData combined = new CombinedData(); combined.A = k1.A; combined.B = k1.B; combined.fA = k2.fA; combined.fB = k2.fB; combined.fC = k2.fC; combined.fAString = k3.fA; // 批量写入 WriteBatch writeBatch = db.batch(); writeBatch.set(documentReference, combined, SetOptions.merge()); writeBatch.commit();
方法3:用update操作批量设置所有字段
通过update方法直接指定每个字段的键值对,同一文档的多次update在批量中会合并为一次操作:
WriteBatch writeBatch = db.batch(); // 逐个设置所有字段 writeBatch.update(documentReference, "A", k1.A, "B", k1.B, "fA", k2.fA, // 若K3的fA需要保留,这里要调整字段名避免冲突 "fB", k2.fB, "fC", k2.fC, "fAString", k3.fA ); writeBatch.commit();
注意事项
- 字段名重复会导致覆盖(比如K2的
fA和K3的fA),需要提前重命名字段或做类型兼容处理; - 以上所有方法均仅计入1次Firestore写入,避免了嵌套监听的多次写入消耗。
内容的提问来源于stack exchange,提问作者Nsqr
相关产品推荐
相关产品推荐

