【web项目 数据字典 05】
一、数据字典介绍
数据字典就是管理系统常用的分类数据或者一些固定数据,例如:省市区三级联动数据、名族数据、行业数据、学历数据等,由于系统大量使用这种数据,所以我们要做一个数据管理方便管理系统,一般系统基本都会做数据管理。
二、数据字典列表的开发
1、页面效果
其实就是多层数据展示的表单
2、数据分析
列表重点在于多层级之间的联动,即根据上级id获取下级数据(构造树形数据),所以在设计数据库表的时候两个字段:id、parent_id来标记上下级关系(上级id、通过id与parent_id构建上下级关系
、例如:我们要获取所有行业数据,那么只需要查询parent_id=20000的数据)
3、开发数据字典列表-主要是开发service-cmn模块-service
@Service public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService { //根据数据id查询子数据列表 @Override public List<Dict> findChlidData(Long id) { QueryWrapper<Dict> wrapper = new QueryWrapper<>(); wrapper.eq("parent_id",id); List<Dict> dictList = baseMapper.selectList(wrapper); // 向list集合每个dict对象中设置hasChildren for(Dict dict:dictList){ Long dictId = dict.getId(); boolean isChild = this.isChildren(dictId); dict.setHasChildren(isChild); } return dictList; } // 判断id下面是否有子节点 private boolean isChildren(Long id) { QueryWrapper<Dict> wrapper = new QueryWrapper<>(); wrapper.eq("parent_id",id); Integer count = baseMapper.selectCount(wrapper); return count>0; } }
Wrapper是mp中查询的高级用法,相当于where条件
三、读写Excel表格
1、EasyExcel介绍:是一个基于Java的简单,省内存的读写Ecxel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel
文档地址:https://alibaba-easyexcel.github.io/index.html
github地址:https://github.com/alibaba/easyexcel
2、EasyExcel完成excel的读写
1)pom文件添加依赖
<dependencies> <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.1.1</version> </dependency> </dependencies>
2)TestWrite -写入Excel的类
第一步:先创建一个实体类UserData
@Data public class UserData { @ExcelProperty(value = "用户编号",index = 0) private int uid; @ExcelProperty(value = "用户名称",index = 1) private String username; } /* 该类的属性就是excel中的列, 比如:excel只需要写入两列:用户编号uid、用户名称username 那么属性就只有这两个,如果需要写入三列那么属性就是三个 */
第二步:编写写入代码
public class TestWrite { public static void main(String[] args) { //构建数据list集合 List<UserData> list = new ArrayList(); for (int i=0;i<10;i++) { UserData data = new UserData(); data.setUid(i); data.setUsername("lucy"+i); list.add(data); } //设置excel文件路径和文件名称 String fileName = "/Users/mobvista/Desktop/01.xlsx"; /* * 调用方法实现写操作: * write方法中fileName参数表示:excel路径;UserData.class表示:写入的内容取之于UserData实体类的属性 * shell("用户信息"):给excel的sheet页起一个名称 * doWrite(list):具体写入的数据,是一个list集合 * */ EasyExcel.write(fileName, UserData.class).sheet("用户信息") .doWrite(list); } }
第三步:查看Excel中写入的数据
3、TestRead -读取Excel的类
第一步:先写一个监听类ExcelListener
public class ExcelListener extends AnalysisEventListener<UserData> { //一行一行读取excel内容,从第二行读取 @Override public void invoke(UserData userData, AnalysisContext analysisContext) { System.out.println(userData); } @Override public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) { System.out.println("表头信息:"+headMap); } //读取之后执行 @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { } }
第二步:编写读取Excel代码 -->实现两个操作:单纯的读取、读取后再写入
public class TestRead { public static void main(String[] args) { // 读取文件路径 String fileName = "/Users/mobvista/Desktop/01.xlsx"; /* * 调用方法实现读取操作 * doRead():直接读取,此方法无返回,读取的内容会直接打印到终端 * doReadSync():读取的结果返回的是一个list -->此段代码的意思是读取01.xlsx然后在写入02.xlsx * */ EasyExcel.read(fileName, UserData.class,new ExcelListener()).sheet().doRead(); List<UserData> list = EasyExcel.read(fileName, UserData.class, new ExcelListener()).sheet().doReadSync(); String fileName1 = "/Users/mobvista/Desktop/02.xlsx"; EasyExcel.write(fileName1, UserData.class).sheet("用户信息") .doWrite(list); } }
四、数据字典的导入导出 (EasyExcel项目中的实践)
1、导出
整体思路:把数据库中的数据导出到Excel中,controller是实现对外的api接口,核心实现导出的代码在service中
controller类
@ApiOperation(value = "数据字典导出") @GetMapping("exportData") public Result exportData(HttpServletResponse response){ //导出一般是按照条件进行的导出比如路径,名字等所以传一个response的参数 dictService.exportData(response); return Result.ok(); }
service类
//数据字典导出 @Override public void exportData(HttpServletResponse response) { try { //设置下载信息 response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("utf-8"); String fileName = URLEncoder.encode("数据字典", "utf-8");//这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系 response.setHeader("Content-disposition","attachment;filename="+fileName+".txt"); //查询数据库 List<Dict> dictList = baseMapper.selectList(null); //创建DictEeVo实体类的list集合,用于存放数据库中查出来的dictlist数据 List<DictEeVo> dictVoList = new ArrayList<>(dictList.size()); for(Dict dict:dictList){ DictEeVo dictEeVo = new DictEeVo(); //把dict对象赋值给dictEeVo,作用类似dictEeVo.setId(dict.getId()); BeanUtils.copyProperties(dict,dictEeVo); dictVoList.add(dictEeVo); } EasyExcel.write(response.getOutputStream(), DictEeVo.class).sheet("数据字典").doWrite(dictVoList); } catch (Exception e) { e.printStackTrace(); } }
备注:既然已经有了DIct的实体类,为什么还要创建一个DictEeVo类呢,因为Dict类中的属性都是数据中的所有字段,而我们导出的数据只需要其中的几个字段(前端表格中需要的字段)即可,所以需要把数据库的数据全部取出来然后赋给DictEeVo实体类
2、导入
思路:把excel中的数据导入库内,首先需要通过监听类(DictListener)实现逐行读取并执行导入,然后service实现利用EasyExcel读取,最后用controller包装成接口
DictListener监听类
public class DictListener extends AnalysisEventListener<DictEeVo> { //DictListener要加到数据库,要么调用mapper,要么调用service,这里调用mapper private DictMapper dictMapper; public DictListener(DictMapper dictMapper) { this.dictMapper = dictMapper; } //一行一行的读取 @Override public void invoke(DictEeVo dictEeVo, AnalysisContext analysisContext) { //调用DictMapper写入数据库 Dict dict = new Dict(); BeanUtils.copyProperties(dictEeVo,dict); dictMapper.insert(dict); } //读取后执行导入 @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { } }
service类
//数据字典导入 @Override public void importData(MultipartFile file) { try { EasyExcel.read(file.getInputStream(),DictEeVo.class,new DictListener(baseMapper)).sheet().doRead(); } catch (IOException e) { throw new RuntimeException(e); } }
EasyExcel中new DictListener(baseMapper) 其实就很能直观的表明为什么DictListener要有构造方法即通过声明对象并利用mapper导入数据库
controller类
@ApiOperation(value = "数据字典导入") @PostMapping("importData") public Result importData(MultipartFile file) throws IOException { //MultipartFile类主要作用是实现以表单的形式进行文件上传功能 dictService.importData(file); return Result.ok(); }