一、数据字典介绍
数据字典就是管理系统常用的分类数据或者一些固定数据,例如:省市区三级联动数据、名族数据、行业数据、学历数据等,由于系统大量使用这种数据,所以我们要做一个数据管理方便管理系统,一般系统基本都会做数据管理。
二、数据字典列表的开发
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();
}