背景項目
學生登陸系統 - 之後會根據模板規則進行試卷的抽取,這些試題均直接從數據庫中拿取,然後把抽取完的試題插入到學生試題記錄表來存儲學生試卷,然後把學生的狀態從未登錄更新到已抽卷。第一次拿取時因爲題庫的數據很多,導致界面不能立即拿到數據進行顯示,當用戶進行刷新時因爲整個流程沒有走完而進行的又是插入操作就會導致學生記錄表中出現兩套該學生的試卷
解決思路
主要癥結的英文因爲從數據庫中拿數據比較慢,所以小夥伴再次加了一個預加載將這一門所有的試題在考試前放到Redis的,加一個版本字段進行標識,也就是先查後插,尷尬的就是樂觀鎖只要是用來更新的,如果是插入這個先查的位置放哪呢,並不能解決問題,於是就想在插入的時候有條件的插入就像更新操作時候一樣.然後找到了這個語法
INSERT INTO IF NOT EXISTS
demo
http://www.codebit.cn/mysql/insert-if-not-exists.html
這個是參考的一個小demo,網上的demo基本都是單條數據的插入,因爲我們是集合的插入,在寫sql的時候還是遇到了一點小麻煩,最後還是解決了,代碼如下
<insert id="insertAllPaperRecord" parameterType="com.dmsdbj.itoo.examinationEvaluation.entity.PaperRecordEntity">
insert into t_paper_record
(id,
remark,
operator,
is_delete,
correct_answer,
course_id,
standard_score,
mark_status,
mark_user,
paper_id,
question_type_id,
question_main_id,
paper_type_id,
score,
student_answer,
student_id,
examination_id,
create_time,
update_time,
question_order,
semester_id,
teachclass_id,
is_out_of_order,
is_alias,
pid,
student_answer_array_str)
<foreach collection="list" item="item" index="index" separator="union all" >
SELECT
#{item.id,jdbcType=VARCHAR},
#{item.remark,jdbcType=VARCHAR},
#{item.operator,jdbcType=VARCHAR},
0,
#{item.correctAnswer,jdbcType=LONGVARCHAR},
#{item.courseId,jdbcType=VARCHAR},
#{item.standardScore,jdbcType=DOUBLE},
#{item.markStatus,jdbcType=VARCHAR},
#{item.markUser,jdbcType=VARCHAR},
#{item.paperId,jdbcType=VARCHAR},
#{item.questionTypeId,jdbcType=VARCHAR},
#{item.questionMainId,jdbcType=VARCHAR},
#{item.paperTypeId,jdbcType=VARCHAR},
#{item.score,jdbcType=DOUBLE},
#{item.studentAnswer,jdbcType=LONGVARCHAR},
#{item.studentId,jdbcType=VARCHAR},
#{item.examinationId,jdbcType=VARCHAR},
now(),
now(),
#{item.questionOrder,jdbcType=TINYINT},
#{item.semesterId,jdbcType=VARCHAR},
#{item.teachclassId,jdbcType=VARCHAR},
#{item.isOutOfOrder,jdbcType=TINYINT},
#{item.isAlias,jdbcType=TINYINT},
#{item.pid,jdbcType=VARCHAR},
#{item.studentAnswerArrayStr,jdbcType=LONGVARCHAR}
FROM DUAL
WHERE
NOT EXISTS
(SELECT * FROM t_paper_record where paper_id=#{item.paperId} and student_id=#{item.studentId} and is_delete=0)
</foreach>
</insert>
後記:
網上說當併發時會查生死鎖,不過應該不影響這個功能的實現