条件:
首先存储的列表字段有 id(String 类型) 和 status(只有 1 和 -1 两个状态,且状态只能从 1 修改为 -1,反之不行) 只有 id 和 status 都相同才算是同一个对象 如何保证三个数据库的数据一样呢?
因为数据库一个是手机日历,一个是手机 SQLite,一个是服务器 Mysql,所以也没有办法在数据库上想办法
想问下大伙儿,有更好的方法吗?我感觉我这个就是一个最基础的笨方法
我是这样做的,先拿 A 和 B 同步,保证 A\B 数据是一致的 再拿 A 和 C 做同步,当需要修改 A 的时候,同时也修改 B
大致代码是这样的:
public class Test {
public static void main(String[] args) {
HashMap<String, Bean> mapA = new HashMap<>(16);
HashMap<String, Bean> mapB = new HashMap<>(16);
HashMap<String, Bean> mapC = new HashMap<>(16);
// A、B 两个数据库同步
for (String key : mapA.keySet()) {
if (mapB.containsKey(key)) {
if (mapA.get(key).getStatus() != mapB.get(key).getStatus()) {
if (mapB.get(key).getStatus() == 1) {
// 将 B 数据库当中的 status 修改为 -1
}
}
} else {
// 将 mapA 中 key 对应的 value 插入到 数据库 B 当中
}
}
for (String key : mapB.keySet()) {
if (mapA.containsKey(key)) {
if (mapB.get(key).getStatus() != mapA.get(key).getStatus()) {
if (mapA.get(key).getStatus() == 1) {
// 将 A 数据库当中的 status 修改为 -1
}
}
} else {
// 将 mapB 中 key 对应的 value 插入到 数据库 A 当中
}
}
//以上操作保证了 A、B 两个数据库是同步的
//然后再拿 A 和 C 两个数据库做同步
//还是同样的逻辑,但是当需要修改 A 的数据的时候,同时也修改 B 数据库
for (String key : mapA.keySet()) {
if (mapC.containsKey(key)) {
if (mapA.get(key).getStatus() != mapC.get(key).getStatus()) {
if (mapC.get(key).getStatus() == 1) {
// 将 C 数据库当中的 status 修改为 -1
}
}
} else {
// 将 mapA 中 key 对应的 value 插入到 数据库 C 当中
}
}
for (String key : mapC.keySet()) {
if (mapA.containsKey(key)) {
if (mapC.get(key).getStatus() != mapA.get(key).getStatus()) {
if (mapA.get(key).getStatus() == 1) {
// 将 A 数据库当中的 status 修改为 -1
// 将 B 数据库当中的 status 修改为 -1
}
}
} else {
// 将 mapC 中 key 对应的 value 插入到 数据库 A 当中
// 将 mapC 中 key 对应的 value 插入到 数据库 B 当中
}
}
}
}
class Bean {
private String key;
private int status;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
1
yuikns 2019-03-27 07:50:01 +08:00
我理解日历和 sqlite 都是在本地?那么从结构上说,那么是有一些特别的查询必须用 sqlite 么?本地可以只取手机日历作为数据源么?
|
2
MoHen9 2019-03-27 08:44:24 +08:00 via Android
不太理解问题,但还是说一下吧,可以根据 ID 和 status 复写 entity 的 hashcode 和 equals 方法,这样 map 中的 A/B/C 三张表的数据只有一份被放在 HashMap 或 HashSet 中。
|
3
mooncakejs 2019-03-27 08:49:16 +08:00 via iPhone
多加一个 seq 字段,version 更新的时候顺便更新版本号。同步对比版本号就行
|
4
lixyz OP @yuikns 使用场景是这样的
一个手机 APP,使用到了日历的功能,所以需要日历数据库,同时又添加了一些其他的功能,所以需要本机 SQLite,考虑到了有可能会更换手机,所以要讲数据上传到服务器,以便更换手机时同步数据,所以用到了 Mysql,三个数据库的字段是相同的,所以需要确保三个数据库数据是同步的 |
5
lixyz OP @mooncakejs 添加版本号还需要修改数据库添加字段,可能是最后考虑的手段了
|
6
lixyz OP @MoHen9 你的意思是将三个数据库的数据先全部存在一个 Map 当中,然后再拿这个 Map 依次和三个数据库做比较
之前想过这么做,但是存在一个问题,因为 Map 的 key 是不能重复的,所以 MapAll 只能存一条 ID,而这条 ID 的 status 有可能是 1 也有可能是 -1,那么在和 A B C 做比较的时候,还挺麻烦的,因为你需要确定 ABC 总是否包含 MapAll 的 key,还需要确定这个 key 对应的 Value 是不是相同,这么做好像没比我的方法简单多少。 不知道对于你的方法理解的是不是对的? |
7
mooncakejs 2019-03-27 19:14:24 +08:00
@lixyz 那就写日志,把数据库的更新操作 append 到文件中,同步的时候替换掉 log 文件,从 log 回复数据
|
8
lixyz OP @mooncakejs 哈哈哈哈这么操作更麻烦了。。。
|
9
thesharjah 2019-03-28 22:07:28 +08:00
怎么感觉题目有点悖论?
|
10
thesharjah 2019-03-28 22:09:53 +08:00
status 只能从 1 改为- 1,日历、sqlite、mysql 三个库,总会有主次对吧? 如果主的 status =- 1,次的 status = 1,请问如何保证三个数据库数据一致呢?
如果业务上不会出现这种场景,那么直接把主同步至次就是了 |
11
hayanami 2019-03-29 14:38:13 +08:00
同意楼上,你 A,B,C 三个库都是以 A 的数据为主,B,C 做从库定时同步就可以了。
而且你 mysql 是为了更换手机时同步数据,基本上使用量不大,没有必要即时同步。另外两个库可以通过异步操作,A 库数据变动,异步方法变动 B 库,或者数据库记录更新 log,B,C 可以根据 log 变更 |
12
lixyz OP @thesharjah @hayanami
我没有给这三个数据库分主次 首先 APP 运行的设备肯定是随时联网的,所以在往这三个数据库保存数据的时候,会同时往这三个数据库插入相同的数据,修改(将 status 从 1 修改为 -1 )也是一样的同时进行 但有可能用户在点击了保存的时候网络突然出现了问题,或者是突然关机,这就有可能会导致本地 SQLite 或者 本地日历 或者云端 MySQL 数据没有保存(更新)成功 所以就需要在每次打开 APP 的时候检查一下是否有数据可以同步,并提醒用户进行同步 就按照上面的情形,没有办法确定哪一个数据库是主哪个是次 只需要保证每一个 ObjectId 都存在于 MySQL\SQLite\手机日历当中,并且他们对应的 status 也是相同的 |
13
lixyz OP 顶楼的代码做的就是分别拿每个数据库和其他两个数据库做比较,然后做出修改
但是我感觉有点儿太费劲了,所以想来请教一下有没有其他比较好的比较简单的方法 |
14
thesharjah 2019-04-01 14:46:09 +08:00
@lixyz 所以你设计的时候应该分主次,以某一个为主,另外两个为从库,写入数据时应该首先写入主,写入成功表示本次操作成功,写入失败则操作失败;操作失败可以有一套失败之后的流程,成功之后才是你需要考虑的同步的问题;此时同步就不会有 status 只能 1 改为- 1 的问题了,同步只是需要保证从库与主库一致,不需要关心任何业务逻辑关系
|
15
lixyz OP @thesharjah 说的有道理。。。感谢感谢
|