feat(新增): 读取和写入Excel表

Signed-off-by: bunny <1319900154@qq.com>
This commit is contained in:
bunny 2024-03-26 09:50:12 +08:00
parent fa58dad04b
commit 1dd176a1af
9 changed files with 156 additions and 40 deletions

View File

@ -0,0 +1,46 @@
package com.atguigu.spzx.manger.excel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.util.ListUtils;
import com.atguigu.spzx.manger.mapper.CategoryMapper;
import com.atguigu.spzx.model.vo.product.CategoryExcelVo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.RequiredArgsConstructor;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
@RequiredArgsConstructor
public class CategoryExcelListener<T> extends AnalysisEventListener<T> {
// 每个5条存储数据库方便垃圾回收
private static final int BATCH_COUNT = 100;
// 缓存的数据
private final List<CategoryExcelVo> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
private CategoryMapper categoryMapper;
@Override
public void invoke(T t, AnalysisContext analysisContext) {
CategoryExcelVo data = (CategoryExcelVo) t;
cachedDataList.add(data);
if (cachedDataList.size() >= BATCH_COUNT) {
saveData();
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
// excel解析完毕以后需要执行的代码
// 这里也要保存数据确保最后遗留的数据也存储到数据库
saveData();
}
/**
* 写入数据库
*/
private void saveData() {
categoryMapper.batchInsert(cachedDataList);
}
}

View File

@ -1,4 +1,4 @@
package com.atguigu.excel; package com.atguigu.spzx.manger.excel;
import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.excel.event.AnalysisEventListener;

View File

@ -1,6 +1,7 @@
package com.atguigu.spzx.manger.mapper; package com.atguigu.spzx.manger.mapper;
import com.atguigu.spzx.model.entity.product.Category; import com.atguigu.spzx.model.entity.product.Category;
import com.atguigu.spzx.model.vo.product.CategoryExcelVo;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import java.util.List; import java.util.List;
@ -22,4 +23,18 @@ public interface CategoryMapper {
* @return int * @return int
*/ */
int countByParentId(Long id); int countByParentId(Long id);
/**
* 读取所以分类数据
*
* @return 分类实体类列表
*/
List<Category> selectAll();
/**
* 批量插入数据库
*
* @param cachedDataList Excel表品牌管理实体类
*/
void batchInsert(List<CategoryExcelVo> cachedDataList);
} }

View File

@ -1,11 +1,15 @@
package com.atguigu.spzx.manger.service.impl; package com.atguigu.spzx.manger.service.impl;
import com.alibaba.excel.EasyExcel; import com.alibaba.excel.EasyExcel;
import com.atguigu.exception.BunnyException;
import com.atguigu.spzx.manger.excel.ExcelListener;
import com.atguigu.spzx.manger.mapper.CategoryMapper; import com.atguigu.spzx.manger.mapper.CategoryMapper;
import com.atguigu.spzx.manger.service.CategoryService; import com.atguigu.spzx.manger.service.CategoryService;
import com.atguigu.spzx.model.entity.product.Category; import com.atguigu.spzx.model.entity.product.Category;
import com.atguigu.spzx.model.vo.product.CategoryExcelVo; import com.atguigu.spzx.model.vo.product.CategoryExcelVo;
import com.atguigu.spzx.model.vo.result.ResultCodeEnum;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -19,6 +23,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
@Service @Service
@Slf4j
public class CategoryServiceImpl implements CategoryService { public class CategoryServiceImpl implements CategoryService {
@Autowired @Autowired
private CategoryMapper categoryMapper; private CategoryMapper categoryMapper;
@ -50,7 +55,29 @@ public class CategoryServiceImpl implements CategoryService {
*/ */
@Override @Override
public void exportData(HttpServletResponse response) { public void exportData(HttpServletResponse response) {
// TODO 导出数据 // 设置响应结果类型
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String filename = URLEncoder.encode("分类数据", StandardCharsets.UTF_8);
response.setHeader("Content-disposition", "attachment;filename=" + filename + ".xlsx");
// 查询数据库中的数据
List<Category> categoryList = categoryMapper.selectAll();
ArrayList<CategoryExcelVo> excelVoArrayList = new ArrayList<>();
// 将从数据库中查询到的Category对象转换成CategoryExcelVo对象
categoryList.forEach(category -> {
CategoryExcelVo vo = new CategoryExcelVo();
BeanUtils.copyProperties(category, vo, CategoryExcelVo.class);
excelVoArrayList.add(vo);
});
try {
// 写入文件
EasyExcel.write(response.getOutputStream(), CategoryExcelVo.class).sheet("分类数据").doWrite(excelVoArrayList);
} catch (IOException exception) {
log.error("文件写入失败:{}", exception.getMessage());
throw new BunnyException(ResultCodeEnum.WRITE_FILE_ERROR);
}
} }
/** /**
@ -60,6 +87,13 @@ public class CategoryServiceImpl implements CategoryService {
*/ */
@Override @Override
public void importData(MultipartFile file) { public void importData(MultipartFile file) {
// TODO 导入功能 // 创建监听器对象传递mapper对象
ExcelListener<CategoryExcelVo> listener = new ExcelListener<>();
// 调用read方法读取excel数据
try {
EasyExcel.read(file.getInputStream(), CategoryExcelVo.class, listener).sheet().doRead();
} catch (IOException e) {
throw new BunnyException(ResultCodeEnum.DATA_ERROR);
}
} }
} }

View File

@ -8,6 +8,17 @@
id,name,image_url,parent_id,status,order_num,create_time,update_time,is_deleted id,name,image_url,parent_id,status,order_num,create_time,update_time,is_deleted
</sql> </sql>
<!-- 批量插入数据库 -->
<insert id="batchInsert">
insert into category (id, name, image_url, parent_id, status, order_num, create_time, update_time, is_deleted)
values
<foreach collection="cachedDataList" item="item" separator=",">
(#{item.id}, #{item.name}, #{item.image_url}, #{item.parent_id}, #{item.status}, #{item.order_num},
#{item.create_time}, #{item.update_time},
#{item.is_deleted})
</foreach>
</insert>
<!-- 根据分类id查询它下面的所有的子分类数据 --> <!-- 根据分类id查询它下面的所有的子分类数据 -->
<select id="selectByParentId" resultType="com.atguigu.spzx.model.entity.product.Category"> <select id="selectByParentId" resultType="com.atguigu.spzx.model.entity.product.Category">
select select
@ -23,4 +34,13 @@
where parent_id = #{id} where parent_id = #{id}
and is_deleted = 0 and is_deleted = 0
</select> </select>
<!-- 读取所以分类数据 -->
<select id="selectAll" resultType="com.atguigu.spzx.model.entity.product.Category">
select
<include refid="columns"/>
from category
where is_deleted = 0
order by id desc
</select>
</mapper> </mapper>

View File

@ -1,7 +1,7 @@
package com.atguigu.spzx.manger; package com.atguigu.spzx.manger;
import com.alibaba.excel.EasyExcel; import com.alibaba.excel.EasyExcel;
import com.atguigu.excel.ExcelListener; import com.atguigu.spzx.manger.excel.ExcelListener;
import com.atguigu.spzx.model.vo.product.CategoryExcelVo; import com.atguigu.spzx.model.vo.product.CategoryExcelVo;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;

View File

@ -3,13 +3,14 @@ package com.atguigu.spzx.model.entity.product;
import com.atguigu.spzx.model.entity.base.BaseEntity; import com.atguigu.spzx.model.entity.base.BaseEntity;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List; import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data @Data
@Schema(description = "分类实体类") @Schema(description = "分类实体类")
public class Category extends BaseEntity { public class Category extends BaseEntity {
@Schema(description = "分类名称") @Schema(description = "分类名称")
private String name; private String name;
@ -30,5 +31,4 @@ public class Category extends BaseEntity {
@Schema(description = "子节点List集合") @Schema(description = "子节点List集合")
private List<Category> children; private List<Category> children;
} }

View File

@ -1,6 +1,7 @@
package com.atguigu.spzx.model.vo.product; package com.atguigu.spzx.model.vo.product;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@ -8,24 +9,23 @@ import lombok.NoArgsConstructor;
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@Schema(description = "Excel表品牌管理实体类")
public class CategoryExcelVo { public class CategoryExcelVo {
@ExcelProperty(value = "id", index = 0)
@ExcelProperty(value = "id" ,index = 0)
private Long id; private Long id;
@ExcelProperty(value = "名称" ,index = 1) @ExcelProperty(value = "名称", index = 1)
private String name; private String name;
@ExcelProperty(value = "图片url" ,index = 2) @ExcelProperty(value = "图片url", index = 2)
private String imageUrl ; private String imageUrl;
@ExcelProperty(value = "上级id" ,index = 3) @ExcelProperty(value = "上级id", index = 3)
private Long parentId; private Long parentId;
@ExcelProperty(value = "状态" ,index = 4) @ExcelProperty(value = "状态", index = 4)
private Integer status; private Integer status;
@ExcelProperty(value = "排序" ,index = 5) @ExcelProperty(value = "排序", index = 5)
private Integer orderNum; private Integer orderNum;
} }

View File

@ -8,15 +8,16 @@ import lombok.Getter;
@Getter @Getter
public enum ResultCodeEnum { public enum ResultCodeEnum {
SUCCESS(200, "成功"), SUCCESS(200, "成功"),
PERMISSION(401, "没有权限"),
FAIL(500, "失败"), FAIL(500, "失败"),
USE_NOT_EXIST(500, "失败"), USE_NOT_EXIST(500, "失败"),
SERVICE_ERROR(2012, "服务异常"), SERVICE_ERROR(500, "服务异常"),
DATA_ERROR(204, "数据异常"), DATA_ERROR(500, "数据异常"),
LOGIN_AUTH(208, "需要先登陆"), LOGIN_AUTH(500, "需要先登陆"),
LOGIN_MOBLE_ERROR(208, "登录验证失败"), LOGIN_MOBLE_ERROR(500, "登录验证失败"),
ACCOUNT_DEACTIVATION(208, "账户停用"), ACCOUNT_DEACTIVATION(500, "账户停用"),
PERMISSION(209, "没有权限"),
USERNAME_IS_EXISTS(500, "用户名已存在"), USERNAME_IS_EXISTS(500, "用户名已存在"),
WRITE_FILE_ERROR(500, "写入文件失败"),
; ;
private final Integer code; private final Integer code;