- 在分布式项目和互联网项目中不要使用外键约束,在插入数据时自己处理好相关id的关系即可,无需显式使用外键约束,因为这会大大影响crud的效率(如果表B的 a_id 字段显式设置对应为表A的 id 字段,那么如果删除表A的一条记录,而该行数据id仍被表B中的记录引用,那么mysql将报错)。
—以下来源阿里巴巴java开发手册 【强制】不得使用外键与级联,一切外键概念必须在应用层解决。 说明: 以学生和成绩的关系为例, 学生表中的 student_id 是主键,那么成绩表中的 student_id则为外键。如果更新学生表中的
student_id,同时触发成绩表中的 student_id
更新,即为级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;
级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。
-
如果在应用层解决级联删除功能,在连表删除多个表的记录时,规范操作是从子表开始删除,再删除父表数据,避免出现孤儿记录的现象。
-
在项目开发中并不一定非得遵循范式,如嵩阳学院项目中本来在 edu_chapter 表中存储有 course_id 字段,在 edu_vedio 表中存储有 chapter_id 字段,那么我们其实在 edu_vedio 表中是能通过 chapter_id 查到 edu_chapter表中的记录进而查到 edu_course 表的,也符合范式。但是对于互联网项目来说,效率才是最重要的,因此我们设计表的时候可以直接在 edu_video 表中存储有course_id 字段,从而可以直接通过 course_id 字段查询到相应的 video 记录。
-
实现查询嵌套列表的功能时,可以使用两种方案。
-
方案一 像在SubjectService中一样操作,只不过当时是用sql语句嵌套查询,在数据库层面操作,而这里是在业务逻辑层实现
虽然简单但效率低 复杂度是1+N个sql(对每个chaper进行查Vedio)1. 通过course_id获取章节列表 List<Chapter> sql 2. 遍历List<Chapter>{ 通过chapter_id查询List<Vedio> sql }
-
方案二 效率高 1+1个sql
1. 通过course_id获取章节列表 List<Chapter> chapterList sql 2. 通过course_id获取视频列表 List<Video> VideoList sql 3. 对于每一个章节 for (int i = 0; i < chapterList.size(); i++){ 根据chapter创建ChapterVo对象 根据videoList和course_id组装VideoVoList hapterVo.setChildren(videoVoList); } //也即在java层面上对VideoList中数据进行筛选生成chapterVo中的videoList属性