一、数据字典介绍

数据字典就是管理系统常用的分类数据或者一些固定数据,例如:省市区三级联动数据、名族数据、行业数据、学历数据等,由于系统大量使用这种数据,所以我们要做一个数据管理方便管理系统,一般系统基本都会做数据管理。

二、数据字典列表的开发

1、页面效果

数据字典 java设计方案 数据字典项目_数据

其实就是多层数据展示的表单

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中写入的数据

数据字典 java设计方案 数据字典项目_List_02

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实体类

数据字典 java设计方案 数据字典项目_数据_03

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();
    }