如 Blog 的 Tag、帖子的 Tag 等多对多的存储关系。
新增的时候
# 看看哪些存在?
tags = Tags.query.filter(Tags.tag_name.in_(('tag1','tagN'))).all()
# 不存在的入库?
# 存在的更新 relation ?
修改 Blog/帖子的时候再原样处理一次?
还有更加优雅的处理方法吗?
1
hwding 2017-10-04 10:05:01 +08:00
我也是这样的,首先处理 Tags,再保存 Blog。
当然你需要一个 mapper 表来保存对应关系。 只新建没有的 Tags。 public List<Tag> saveWithMetas(String[] metas) { List<Tag> tags = Arrays.asList(metas) .parallelStream() .map(name -> { Tag thisTag = findTagByName(name); return thisTag == null ? new Tag().setName(name) : thisTag; }) .distinct() .collect(Collectors.toList()); return tagRepository.save(tags); } 目前没看到更好的方案,而且多对多有一个遗孤(Orphan)的问题,不能自动清除掉没用的 Tags... |
2
Sight4 2017-10-04 10:10:16 +08:00
1. 部分 rmdbs/nosql 提供 insert...update...语句,例如 mysql 的 insert..on duplicate key update 或者 postgresql 的 insert...on conflict update 都支持类似的方案,插入时重复时更新或者忽略
2. 触发器或者存储过程解决 |
3
cevincheung OP @hwding #1
有个中间表还好,每次编辑都直接删掉当前对象的所有关联然后重建。 |
4
cevincheung OP @Sight4 #2 触发器存储过程会不会在后端数据库集群多 Master 情况下有问题。
|
5
Sight4 2017-10-04 10:30:20 +08:00
@cevincheung 这个要看你多 master 的配置方式,比如说主动-被动模式下的双主不存在这个问题,这种模式下其实就相当于热备,如果是主动-主动模式的就会出现问题了,同时允许多个 master 写入是件很高风险的事情
|
6
qiukun 2017-10-04 12:05:02 +08:00
API 纯 rest 的话是一系列 update 操作,不过也可以抽象一个 tags 资源,blog/id/tags update 即可。
实际实现,不考虑性能就是多对多,中间表。 考虑性能中间肯定顶一层 cache 了,读取全走 cache,写 db 的话异步写,这里有一致性的问题,如果用 redis 的话,就没有,建议用 redis,tag#{blog_id} -> set blog#{tag_id} -> set。 其实不考虑性能也用 redis 吧,每次改 blog 的 tags 你都不知道用户是不是改过原有的 tags,都是要走中间表查一次,虽然说写起来也无非就是 blog.tags.destory blog.tags.insert (这种操作看贵 ORM 了。。) |