优化之前的代码,大家可以点我头像看上篇文章!
简单回顾优化前代码:
// 添加问卷
ProductQuestionnairePO questionnairePO = new ProductQuestionnairePO();
// 将相同属性的值转换到questionnairePO实体类中
BeanUtils.copyProperties(paramDTO,questionnairePO);
questionnairePO.setOwnerCode(ownerCode);
questionnairePO.setIsRelease(Integer.parseInt(CommonConstants.DICT_IS_NO));
questionnairePO.insert();
// 获取到新增的问卷id
String questionnaireId = questionnairePO.getQuestionnaireId();
for (QuestionDTO questionDTO : paramDTO.getQuestionList()) {
if (StringUtils.isNullOrEmpty(questionDTO.getQuestionContent())){
throw new ServiceBizException("问题内容不能为空");
}
if (StringUtils.isNullOrEmpty(questionDTO.getQuestionOrder())){
throw new ServiceBizException("问题顺序不能为空");
}
if (StringUtils.isNullOrEmpty(questionDTO.getIsRequired())){
throw new ServiceBizException("问题是否必填不能为空");
}
if (StringUtils.isNullOrEmpty(questionDTO.getQuestionType())){
throw new ServiceBizException("问题类型不能为空");
}
ProductQuestionPO questionPO = new ProductQuestionPO();
// 将相同属性的值copy到PO实体类中
BeanUtils.copyProperties(questionDTO, questionPO);
questionPO.setOwnerCode(ownerCode);
questionPO.setQuestionnaireId(questionnaireId);
questionPO.setUuid(String.valueOf(UUID.randomUUID()));
questionPO.insert();
// 获取到新增的问题id
String questionId = questionPO.getQuestionId();
// 添加对应答案
if (!StringUtils.isNullOrEmpty(questionDTO.getAnswerList())){
for (AnswerDTO answerDTO : questionDTO.getAnswerList()) {
if (StringUtils.isNullOrEmpty(answerDTO.getAnswerContent())){
throw new ServiceBizException("答案内容不能为空");
}
ProductAnswerPO answerPO = new ProductAnswerPO();
BeanUtils.copyProperties(answerDTO,answerPO);
answerPO.setOwnerCode(ownerCode);
answerPO.setQuestionnaireId(questionnaireId);
answerPO.setQuestionId(questionId);
answerPO.insert();
}
}
}
}
业务可以完成,但因for循环嵌套导致效率低下,接下来我们对此进行Mybatis的优化
批量插入优化
SQL语句:
INSERT INTO
[表名]([列名],[列名])
VALUES
([列值],[列值])),
([列值],[列值])),
([列值],[列值]));
由此,我想大家的优化思路也已经想到了,那就是将本在业务中多次循环的业务批量加载到XML文件中。
业务代码优化
在上述代码第 9 行开始进行了优化。
if (!StringUtils.isNullOrEmpty(paramDTO.getQuestionList())) {
List<ProductQuestionPO> questionList = new ArrayList<>();
paramDTO.getQuestionList().forEach(e -> {
ProductQuestionPO questionPO = new ProductQuestionPO();
BeanUtils.copyProperties(e, questionPO);
questionList.add(questionPO);
});
// 批量插入问题
productQuestionMapper.addQuestionList(questionList,questionnaireId);
}
- 首先判断业务中是否有问题需要添加。
- 若有,循环此问题List将DTO中的数据copy到PO中(不懂DTO和PO的同学可以看我上篇文章)。
- 将每个问题添加到空数组中。
- 调用Mapper中的添加问题接口。
XML文件优化(重要!)
void addQuestionList(@Param("questionList") List<ProductQuestionPO> questionList, @Param("questionnaireId") String questionnaireId)
<!--批量插入问题-->
<insert id="addQuestionList" parameterType="list" useGeneratedKeys="true" keyProperty="questionList.questionId">
insert into tm_product_question(owner_code,questionnaire_id,UUID,
QUESTION_CONTENT,QUESTION_ORDER,QUESTION_TYPE,IS_REQUIRED)
values
<foreach collection="questionList" item="item" index="index" separator=",">
(
#{ownerCode},#{questionnaireId},#{item.uuid},
#{item.questionContent},#{item.questionOrder},#{item.questionType},#{item.isRequired}
)
</foreach>
</insert>
- parameterType :输入类型为list
- useGeneratedKeys :在执行添加记录之后可以获取到数据库自动生成的主键ID
- keyProperty :返回新增后的ID
- collection :需要循环的字段
- item :列表中的每行数据
- separator :分隔符
由此可以进行批量插入,在效率上要比for循环高很多,特别是在大量数据的情况下!