标签:
2016/07/13更新
整个实习已经告一段落了,其实整个问卷模块的数据库设计,在6月初基本上已经最终敲定并实现出来了。
本次的总结分为两个部分。
一、对之前提出的几个遗留问题,解决了的做一个说明
二、最终总结一下,问卷模块的核心:问卷、试题、选项几个实体之间的关系如何表示,如实记录之中的心路历程,以及遇到过的一些坑。
一。之前遗留问题
1.结果试题标签
这个结果标签其实不是难点,到时候只需要记录获得的结果标签的id即可。
一次问卷的评价当然可以获得,若干个结果标签。同一个结果标签也可以被不同问卷所持有。
所以问卷:结果标签是n:n关系。
①可以使用关联表实现
②可以在评价结果记录中使用一个字符串来记录所有得到的结果标签id
这个标签模块,后来准备做成一个通用模块。
比较复杂的逻辑是如何根据用户的答案以及评价规则得到结果标签的id。
不过这不是本帖的内容。
2.试题序号
这个很多都可以由前端实现了。
但是当时我还是进行了实现的。
如果两个实体的关系是1:n,实现采用的是持有id实现,可以直接把序号维护在n的字段之中
比如,选项在试题中的序号(最终采用的是选项持有试题id)
如果两个实体的关系是n:n,实现采用的是关联表,那么序号应该放在关联表中
比如,试题在问卷中的序号
如果只是自身的序号,就直接放在自身字段之中
比如,问卷的序号、问卷类型的序号
①增
新增一个记录,序号赋值为,查询已有记录,然后count出来。
②删
删除一个记录,查询到序号大于被删除的记录的所有记录,对其序号字段进行批量减一操作。
③删除多个
在删除类型时,由于删除类型需要将其子类型一起逻辑删除,这个时候不确定会对哪些字段删除,不知道删除多少个。
采用的办法是,查询所有剩余的字段,按序号升序排序,然后统一遍历重新设定其序号。
3.填空题
未解决
4.父子试题、选项与隐藏试题
未实现
5.类型的删改策略
①删除采用逻辑删除
对字段N_IS_DELETE进行赋值。
删除后,新增加类型看不见已经删除了的。问卷选择类型也看不见已经删除了的。
但是已经选择了的,不会受到删除的影响。
特别注意,层级结构的话,删除需要对其子类别一同删除。
②编辑
内容当然可以编辑,但是层级结构不允许编辑
二。问卷模块的设计
最重要的就是三个实体:问卷(paper)、试题(question)、选项(option)
1.设计一
paper和question是关联表
option最开始的想法是,同一个题目,在不同的paper中,可以有不同的选项,并且拥有不同的分值。
当时采用的就是option持有paperId和questionId
优点:
①不同的试卷,对同一个题目的选项的修改是互不影响的
②同一个题目可以拥有不同的选项,提供了更大的灵活性
缺点:
如果有paper1和paper2都有试题6,这个时候paper3同时从paper1中导入了试题x,记为ques1,也从paper2中导入了试题6,记为ques2。
①选项窜了
对于paper3,ques1和ques2是不同的两道题。
然而,由于选项的设计,持有paperId和持有questionId,这个时候ques1的选项和ques2的选项共用了。
修改ques1的选项会完全反映到ques2上面。
这种情况虽然很难出现,但是由于我们就是希望提供统一题干,不同选项的灵活性,这个bug是实实在在存在的。
②导入试题不方便
这个时候导入试题,你会发现你只能导入题干,导入过来的试题,如果不指定试卷的话,导入过来的试题是没有选项的。
综合①、②我们只能修改设计。
2.设计二
如图所示
paper与question关闭不变
option牺牲一部分的灵活性与question绑定。
也就是说,除了分数以外,不同的试卷导入同一个试题,其题干以及所有选项内容是一样的。
这样试题和选项就是1:n关系,采用选项持有试题id即可。
由于还是需要维护不同试卷的同一试题同一选项的不同分值,
而试卷有多个选项,选项也可以对应不同的问卷,所以是n:n关系,所以这个时候问卷、选项也需要一张关联表。
该关联表字段有paperId、optionId、score
优点:
①选项与试题绑定以后,避免了一些麻烦,比如之前提到的串扰问题。
②导入试题的时候可以不用管问卷了,因为选项内容只与试题相关。
缺点:
①选项与试题绑定之后,也带来了新的缺点。不同的问卷导入同一道试题,会相互影响。
而这个影响本身也有好有坏。
如果希望对所有的问卷一起修改,当然很方便。
如果不希望别人的修改影响到自己,则无能为力。
②显示选项的分数有很大的麻烦。
A。通过问卷id,查询所有的试题id。通过某个试题id,查询所有的选项id,显示选项的内容。
B。通过问卷id,选项id在关联表中,查询选项的分数。
C。如果对于某个选项就需要查询一次数据库,代价太大。
如果查询问卷所有选项的分数,将分数与对应的想象匹配起来,异常地复杂。
解决办法:
针对②,解决办法是,修改问卷-选项关联表
将里面的字段改为paperId,questionId,optionName,score
这样将分数按选项的名称(A,B,C,D)单独显示在旁边,避免了配对的问题。
因为以选项名称来存储,所以无法区分不同试题的选项,所以又加入了questionId字段
针对①,开始我们想到了,先进行判断(通过在关联表中查询count某个试题,看是否等于1)。
如果某个试题没有被其他问卷导入,当然可以直接修改。
如果被多个问卷导入,那么将决定权给用户,在每次进行修改的时候告知用户这样修改可能会影响到其他试卷。
3.设计三
其实在设计二中,针对①的办法还存在着难以忍受的问题。
如果一个用户新建了一个题目,但是它还没有创建选项。
这个时候他有事儿走了,但是别的用户导入了该题目。
后来该用户回来开始创建选项,这个时候,它每创建一个选项,就会被问及这个修改会影响到别人,是否修改。
这个体验是不可忍受的。
在这种设计之下,试题和选项是绑定了的,
那么对于试题的修改就会有一下4种情况:
①对于试题内容的修改,比如修改题干。
②增加选项
③修改选项内容
④删去选项
而在这种不同问卷共享导入题目的设计有一个一直没有解决的矛盾:
对于一个人修改,所有人跟着变的共用
与自己所引用的东西,不希望别人修改影响到自己的不共用
共用与不共用的矛盾
最终我采用的折衷解决办法如下:
题目加入一个创建人字段
题目增加一个权限字段:①不可导入(这种权限的题目根本不会出现在导入列表中)②可导入,只能自己修改③可导入,任何人可以修改
权限编辑是单独的。只有当前操作人=题目创建人,可以进行权限编辑
普通编辑:
(1)若试题权限为不可导入,直接修改
(2)若试题权限为可导入,只能自己修改
①操作人=题目创建人,直接修改
②操作人!=题目创建人,弹出提示不能修改
(3)若试题权限为可导入,任何人可以修改,直接修改
导入分为两种:
(1)关联导入
导入直接将当前问卷与某个题目关联。复制问卷-试题-选项关联表记录即可。
关联导入的创建人不变。权限也不变。
(2)独立导入
复制一个问题,将其单独保存,再和当前试卷关联,再复制问卷-试题-选项关联表。
问题创建人修改为导入的操作人,权限默认修改为不可导入。
独立导入功能的加入,使得别人设置为可导入,只能创建人自己修改权限的试题在不具备编辑权限,自己又想编辑的时候,可以导入过来,进行编辑。
权限编辑功能,使得可以随时将不可导入的试题分享出来给别人。
在权限控制下,所有能够的修改都可以直接修改,修改引起的其他试卷修改,由用户自己负责。
标签:
原文地址:http://blog.csdn.net/u010087886/article/details/51902961