安卓开发中使用嵌入式RealmObject如何避免保存重复数据?
解决方案
以下是不需要修改嵌入式类设计、也不需要给MonthlyLog加主键的可行方案:
插入前做业务层去重校验
嵌入式对象完全依附于父对象Product存在,每次插入新的月日志前,先遍历当前Product的monthlyLogs列表,判断是否已有同年月的记录:存在就直接更新原有记录的消耗量,不存在再插入新记录。按月存储的日志单产品下最多只有几十上百条,遍历开销完全可以忽略。
代码示例:public void addMonthlyLog(String productMac, MonthlyLog newLog) { try (Realm realm = Realm.getDefaultInstance()) { Product targetProduct = realm.where(Product.class) .equalTo("macAddress", productMac) .findFirst(); if (targetProduct == null) return; MonthlyLog existLog = null; for (MonthlyLog log : targetProduct.monthlyLogs) { if (log.getYear() == newLog.getYear() && log.getMonth() == newLog.getMonth()) { existLog = log; break; } } realm.beginTransaction(); if (existLog != null) { // 已有重复记录,直接更新数值即可 existLog.setConsumption(newLog.getConsumption()); } else { targetProduct.monthlyLogs.add(newLog); } realm.commitTransaction(); } }用Realm嵌入式对象查询能力做校验
如果不想手动遍历列表,可以直接通过Realm的反向关联查询,直接定位当前产品下是否有匹配年月的日志,效率更高:MonthlyLog existLog = realm.where(MonthlyLog.class) .equalTo("year", newLog.getYear()) .equalTo("month", newLog.getMonth()) .equalTo("$parent.macAddress", productMac) .findFirst();封装统一的插入入口避免漏校验
把上述去重逻辑封装为统一的工具类方法,所有业务代码插入月日志时必须调用该方法,从编码规范层面避免漏做校验导致的重复数据。重写
MonthlyLog的equals方法统一去重规则
如果你后续可能调整重复判断的维度,可以直接在类中重写equals和hashCode方法,所有判断重复的逻辑都复用该方法,避免散落在业务代码中不好维护:@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; MonthlyLog that = (MonthlyLog) o; return month == that.month && year == that.year; } @Override public int hashCode() { return Objects.hash(month, year); }
内容的提问来源于stack exchange,提问作者Yusuf Yıldırım
相关产品推荐
相关产品推荐

