目录
一、数据字典
(一)、什么是数据字典
(二)、数据字典的设计
二、Excel数据批量导入
(一)后端接口
1、添加依赖
2、创建Excel实体类
3、创建监听器
4、Mapper层批量插入
5、Service层创建监听器实例
6、controller层接受客户端请求
7、添加mapper发布配置
8、Swagger接口测试
(二)前端调用
1、创建页面组件
2、配置路由
3、数据导入
一、数据字典
(一)、什么是数据字典
何为数据字典?数据字典负责管理系统常用的分类数据或者一些固定数据,例如:省市区三级联动数据、民族数据、行业数据、学历数据等,数据字典帮助我们方便的获取和适用这些通用数据。
(二)、数据字典的设计
- parent_id:上级id,通过id与parent_id构建上下级关系,例如:我们要获取所有行业数据,那么只需要查询parent_id=20000的数据
- name:名称,例如:填写用户信息,我们要select标签选择民族,“汉族”就是数据字典的名称
- value:值,例如:填写用户信息,我们要select标签选择民族,“1”(汉族的标识)就是数据字典的值
- dict_code:编码,编码是我们自定义的,全局唯一,例如:我们要获取行业数据,我们可以通过parent_id获取,但是parent_id是不确定的,所以我们可以根据编码来获取行业数据
二、Excel数据批量导入
(一)后端接口
1、添加依赖
在srb-core中pom.xml添加依赖
com.alibabaeasyexcelorg.apache.xmlbeansxmlbeans
2、创建Excel实体类
package com.atguigu.srb.core.pojo.dto;@Datapublic class ExcelDictDTO {@ExcelProperty("id")// 和Excel文件的列名匹配private Long id;@ExcelProperty("上级id")private Long parentId;@ExcelProperty("名称")private String name;@ExcelProperty("值")private Integer value;@ExcelProperty("编码")private String dictCode;}
3、创建监听器
package com.atguigu.srb.core.listener;@Slf4j//@AllArgsConstructor //全参@NoArgsConstructor //无参public class ExcelDictDTOListener extends AnalysisEventListener {/** * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收 */private static final int BATCH_COUNT = 5;List list = new ArrayList();private DictMapper dictMapper;//传入mapper对象public ExcelDictDTOListener(DictMapper dictMapper) {this.dictMapper = dictMapper;}/** *遍历每一行的记录 * @param data * @param context */@Overridepublic void invoke(ExcelDictDTO data, AnalysisContext context) {log.info("解析到一条记录: {}", data);list.add(data);// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOMif (list.size() >= BATCH_COUNT) {saveData();// 存储完成清理 listlist.clear();}}/** * 所有数据解析完成了 都会来调用 */@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {// 这里也要保存数据,确保最后遗留的数据也存储到数据库saveData();log.info("所有数据解析完成!");}/** * 加上存储数据库 */private void saveData() {log.info("{}条数据,开始存储数据库!", list.size());dictMapper.insertBatch(list);//批量插入log.info("存储数据库成功!");}}
4、Mapper层批量插入
接口:DictMapper
一开始脑抽了在想为什么方法不写在service层,要写在mapper层,因为它要写sql语句!!!而mybatisPlus没有现有的方法供调用
void insertBatch(List list);
xml:DictMapper.xml
insert into dict (id ,parent_id ,name ,value ,dict_code) values(#{item.id} ,#{item.parentId} ,#{item.name} ,#{item.value} ,#{item.dictCode})
5、Service层创建监听器实例
接口 DictService
void importData(InputStream inputStream);
实现:DictServiceImpl
注意:此处添加了事务处理,默认情况下rollbackFor = RuntimeException.class
@Transactional(rollbackFor = {Exception.class})@Overridepublic void importData(InputStream inputStream) {// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭EasyExcel.read(inputStream, ExcelDictDTO.class, new ExcelDictDTOListener(baseMapper)).sheet().doRead();log.info("importData finished");}
6、controller层接受客户端请求
AdminDictController
package com.atguigu.srb.core.controller.admin;@Api(tags = "数据字典管理")@RestController@RequestMapping("/admin/core/dict")@Slf4j@CrossOrigin// 跨域public class AdminDictController {@Resourceprivate DictService dictService;@ApiOperation("Excel批量导入数据字典")@PostMapping("/import")public R batchImport(@ApiParam(value = "Excel文件", required = true)@RequestParam("file") MultipartFile file) {try {InputStream inputStream = file.getInputStream();dictService.importData(inputStream);return R.ok().message("批量导入成功");} catch (Exception e) {//UPLOAD_ERROR(-103, "文件上传错误"),throw new BusinessException(ResponseEnum.UPLOAD_ERROR, e);}}}
7、添加mapper发布配置
注意:因为maven工程在默认情况下src/main/java目录下的所有资源文件是不发布到target目录下的,因此我们需要在pom.xml中添加xml配置文件发布配置
src/main/java**/*.xmlfalse
8、Swagger接口测试
(二)前端调用
1、创建页面组件
创建 src/views/core/dict/list.vue
export default {}
2、配置路由
{path: '/core',component: Layout,redirect: '/core/dict/list',name: 'coreDict',meta: { title: '系统设置', icon: 'el-icon-setting' },alwaysShow: true,children: [{path: 'dict/list',name: '数据字典',component: () => import('@/views/core/dict/list'),meta: { title: '数据字典' }}]},
3、数据导入
在 src/views/core/dict/list.vue编写代码
导入Excel点击上传 取消export default {// 定义数据data() {return {dialogVisible: false, //文件上传对话框是否显示BASE_API: process.env.VUE_APP_BASE_API //获取后端接口地址}},methods: {// 上传多于一个文件时fileUploadExceed() {this.$message.warning('只能选取一个文件')},//上传成功回调fileUploadSuccess(response) {if (response.code === 0) {this.$message.success('数据导入成功')this.dialogVisible = false} else {this.$message.error(response.message)}},//上传失败回调fileUploadError(error) {this.$message.error('数据导入失败')}}}
测试三个回调函数,
测试失败回调函数,数据库中表单没有删除时导入文件会出现主键冲突
测试上传超出文件数量回调函数时,需要将自动上传设置为false,此时选择文件不会自动上传,然后分两次选择文件,超出limit限制会报错
删除数据库记录,导入Excel文件,显示导入成功,弹窗自动关闭