1.情景展示
在实际开发过程中,我们有时候会遇到前端批量提交的数据。
诚然,如果我们使用for循环一次一次插入,也是可以的。
但这会涉及到对数据库频繁操作的问题,有没有更好的办法呢?
2.具体分析
我们可以通过mybatis的批量插入功能来解决这个问题。
只需要操作一次数据库,就能完成多条数据的插入操作。
3.解决方案
XML
<!--批量插入-->
<insert id="addFlinkDataFieldBatch" parameterType="java.util.List">
insert into flink_data_field
(pipelineid, DATABASEID_SOURCE, TABLENAME_SOURCE, FIELDNAME_SOURCE, status, createtime, TABLESTATUS_TARGET)
values
<foreach collection="fieldList" separator="," item="row">
(#{row.pipelineid},#{row.databaseidSource},#{row.tablenameSource},#{row.fieldnameSource}, #{row.status} ,now(), #{row.tablestatusTarget})
</foreach>
</insert>
说明:
这里是mysql数据库,表主键使用的是自增属性,所以插入的时候,可以不用管主键列。
映射层(dao层、mapper层)
Boolean addFlinkDataFieldBatch(List<FlinkDataField> fieldList);
说明:
插入成功,返回:true;插入失败,返回:false。
方法入参的参数名称:fileldList,与foreach标签的collection的属性值相对应。
如果不对应的话,也可以,只不过,需要我们使用注解@Param。
Boolean addFlinkDataFieldBatch(@Param("fieldList") List<FlinkDataField> list);
说明:
当方法入参的参数名称与foreach标签的collection的属性值不一致时,我们有两种解决办法。
第1种:修改方法入参的参数名称,使其与foreach标签的collection的属性值保持一致。
第2种:在方法入参的变量类型前面增加@Param注解,使该注解的值与foreach标签的collection的属性值保持一致。
业务层(Bo层)
/**
* 插入管道信息及字段映射信息
* @param pipelineFieldVo
* @return
*/
@Override
public Boolean addPipelineAndField(PipelineFieldVo pipelineFieldVo) {
// 获取管道信息
FlinkDataPipeline pipeline = pipelineFieldVo.getPipeline();
if (null == pipeline) {
// 抛出运行时异常,触发提交事务进行回滚
throw new RuntimeException("管道信息不能为空");
}
// 插入flink_data_pipeline表
Boolean isSuccess = pipelineMapper.addFlinkDataPipeline(pipeline);
// 获取插入的管道主键
Long pipelineid = pipeline.getPipelineid();
if (!isSuccess || pipelineid == null) {// 插入失败
throw new RuntimeException("管道信息保存失败");
}
// 获取表信息
List<TableVo> tables = pipelineFieldVo.getTables();
if (null == tables || tables.isEmpty()) {
throw new IllegalArgumentException("保存失败:字段映射不能为空");
}
List<FlinkDataField> fieldList = new ArrayList<>();
// 遍历取出每个table里面包含的字段映射信息
tables.forEach(tableVo -> {
ColumnVo columnVo = tableVo.getTable();
if (null == columnVo) {
throw new IllegalArgumentException("保存失败:字段映射不能为空");
}
List<FlinkDataFieldVo> columns = columnVo.getColumns();
if (null == columns || columns.isEmpty()) {
throw new IllegalArgumentException("保存失败:字段映射不能为空");
}
columns.forEach(flinkDataFieldVo -> {
FlinkDataField flinkDataField = FlinkDataField.builder().build();
flinkDataField.setPipelineid(pipelineid)// 管道主键
.setDatabaseidSource(columnVo.getDatabaseidSource())
.setDatabaseidTarget(columnVo.getDatabaseidTarget())
.setTablenameSource(columnVo.getTablenameSource())
.setTablenameTarget(columnVo.getTablenameTarget())
.setTablestatusTarget(columnVo.getTablestatusTarget())
;
flinkDataField.setFieldnameSource(flinkDataFieldVo.getFieldnameSource())
.setFieldtypeSource(flinkDataFieldVo.getFieldtypeSource())
.setFieldisnullSource(flinkDataFieldVo.getFieldisnullSource())
.setFieldiskeySource(flinkDataFieldVo.getFieldiskeySource())
.setFieldnameTarget(flinkDataFieldVo.getFieldnameTarget())
.setFieldtypeTarget(flinkDataFieldVo.getFieldtypeTarget())
.setFieldisnullTarget(flinkDataFieldVo.getFieldisnullTarget())
.setFieldiskeyTarget(flinkDataFieldVo.getFieldiskeyTarget())
.setStatus(flinkDataFieldVo.getStatus())
;
// 将表的字段映射关系放到List当中
fieldList.add(flinkDataField);
});
});
return flinkDataFieldMapper.addFlinkDataFieldBatch(fieldList);
}
控制层(Controller层)
@ApiOperation(value = "添加管道信息", notes = "添加管道信息", httpMethod = "POST")
@PostMapping(value = "/add", produces = {"application/json;charset=UTF-8"})
public Boolean addPipelineAndField(@RequestBody @Valid PipelineFieldVo pipelineFieldVo){
return pipelineService.addPipelineAndField(pipelineFieldVo);
}