目录
一、数据字典
(一)、什么是数据字典
(二)、数据字典的设计
二、Excel数据批量导入
(一)后端接口
1、添加依赖
2、创建Excel实体类
3、创建监听器
4、Mapper层批量插入
5、Service层创建监听器实例
6、controller层接受客户端请求
7、添加mapper发布配置
8、Swagger接口测试
(二)前端调用
1、创建页面组件
2、配置路由
3、数据导入
何为数据字典?数据字典负责管理系统常用的分类数据或者一些固定数据,例如:省市区三级联动数据、民族数据、行业数据、学历数据等,数据字典帮助我们方便的获取和适用这些通用数据。
在srb-core中pom.xml添加依赖
com.alibaba
easyexcel
org.apache.xmlbeans
xmlbeans
package com.atguigu.srb.core.pojo.dto;
@Data
public 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;
}
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
*/
@Override
public void invoke(ExcelDictDTO data, AnalysisContext context) {
log.info("解析到一条记录: {}", data);
list.add(data);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (list.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
list.clear();
}
}
/**
* 所有数据解析完成了 都会来调用
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
saveData();
log.info("所有数据解析完成!");
}
/**
* 加上存储数据库
*/
private void saveData() {
log.info("{}条数据,开始存储数据库!", list.size());
dictMapper.insertBatch(list); //批量插入
log.info("存储数据库成功!");
}
}
接口: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}
)
接口 DictService
void importData(InputStream inputStream);
实现:DictServiceImpl
注意:此处添加了事务处理,默认情况下rollbackFor = RuntimeException.class
@Transactional(rollbackFor = {Exception.class})
@Override
public void importData(InputStream inputStream) {
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
EasyExcel.read(inputStream, ExcelDictDTO.class, new ExcelDictDTOListener(baseMapper)).sheet().doRead();
log.info("importData finished");
}
AdminDictController
package com.atguigu.srb.core.controller.admin;
@Api(tags = "数据字典管理")
@RestController
@RequestMapping("/admin/core/dict")
@Slf4j
@CrossOrigin // 跨域
public class AdminDictController {
@Resource
private 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);
}
}
}
注意:因为maven工程在默认情况下src/main/java目录下的所有资源文件是不发布到target目录下的,因此我们需要在pom.xml中添加xml配置文件发布配置
src/main/java
**/*.xml
false
创建 src/views/core/dict/list.vue
{
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: '数据字典' }
}
]
},
在 src/views/core/dict/list.vue编写代码
导入Excel
点击上传
测试三个回调函数,
测试失败回调函数,数据库中表单没有删除时导入文件会出现主键冲突
测试上传超出文件数量回调函数时,需要将自动上传设置为false,此时选择文件不会自动上传,然后分两次选择文件,超出limit限制会报错
删除数据库记录,导入Excel文件,显示导入成功,弹窗自动关闭