EasyExcel导出数据,解决慢sql,漏数据,重复数据问题(一)

EasyExcel导出数据,解决慢sql,漏数据,重复数据问题(一)

大家思考一下,在导出excel时是否会出现如下几个常见问题

  • 慢sql问题
  • 漏数据,缺数据问题
  • 数据重复

那到底该如何解决呢?下面我们一起来看看我的实现吧!

代码示例

  1. controller入口
    分页查询2000条数据,分批次导出。
 /***下载自动续费* @author youlu* @date 2022/11/21 14:32* @param response* @return com.smy.ucc.common.JsonMessage*/@GetMapping("/downloadRenewalSign")public void downloadRenewalSign(HttpServletResponse response, RenewalSignAdminReq req) throws Exception {this.checkDownloadParam(req);response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("橡树会员自动续费", "UTF-8");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), RenewalSignAdminResp.class).build();WriteSheet writeSheet = EasyExcel.writerSheet("自动续费").build();req.setStartCreateTime(DateUtil.parseDate(req.getStartCreateTimeStr() + " 00:00:00", "yyyy-MM-dd HH:mm:ss"));req.setEndCreateTime(DateUtil.parseDate(req.getEndCreateTimeStr() + " 23:59:59", "yyyy-MM-dd HH:mm:ss"));int pageSize = 2000;boolean firstFlag = true;while (true) {List<RenewalSignAdminResp> data = cbsRenewalService.queryRenewalSignListForDownload(req, firstFlag, pageSize);if (CollectionUtils.isEmpty(data)) {break;}Date lastCreateTime = data.get(data.size() - 1).getCreateTime();String startId = data.get(data.size() - 1).getId();//补偿同一时间段内并发的数据 where create_time = ? and id > ? and 其他筛选条件List<RenewalSignAdminResp> otherDatas = cbsRenewalService.queryRenewalSignListByCreateTimeAndId(req, lastCreateTime, startId);data.addAll(otherDatas);excelWriter.write(data, writeSheet);req.setStartCreateTime(lastCreateTime);if (firstFlag) {firstFlag = false;}}excelWriter.finish();}
  1. 实体
package com.smy.cbs.dto.renewal;import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.smy.cbs.easyexcel.write.RenewalStatusStringConverter;
import com.smy.cbs.easyexcel.write.VipTypeStringConverter;
import com.smy.cbs.enums.renewal.RenewalStatusEnum;
import com.smy.cbs.enums.vip.VipType;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.Date;/***自动签约返回参数* @author youlu* @date 2022/9/22 10:19* @return*/
@Getter
@Setter
public class RenewalSignAdminResp implements Serializable {private static final long serialVersionUID = 472574503670404785L;//id:调用框架生成@ExcelProperty(value = "签约号", index = 0)private String id;//客户号@ExcelProperty(value = "客户号", index = 1)private String custNo;/*** 会员类型,1:橡树会员、2:自营会员* @see VipType*/@ExcelProperty(value = "会员类型", index = 2, converter = VipTypeStringConverter.class)private String vipType;//续费周期@ExcelProperty(value = "续费周期", index = 3)private Integer renewalPeriod;//签约时间@ExcelProperty(value = "签约时间", index = 4)@DateTimeFormat("yyyy-MM-dd HH:mm:ss")@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",locale = "zh",timezone="GMT+8")private Date signTime;//解约时间@ExcelProperty(value = "解约时间", index = 5)@DateTimeFormat("yyyy-MM-dd HH:mm:ss")@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",locale = "zh",timezone="GMT+8")private Date terminateTime;/*** 签约状态,1:待签约、2:签约失败、3:签约中、4:已解约* @see RenewalStatusEnum*/@ExcelProperty(value = "签约状态", index = 6, converter = RenewalStatusStringConverter.class)private String renewalStatus;//下次代扣时间@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",locale = "zh",timezone="GMT+8")@DateTimeFormat("yyyy-MM-dd HH:mm:ss")@ExcelProperty(value = "下次代扣时间", index = 7)private Date nextRenewalTime;//自动续费次数@ExcelProperty(value = "自动续费次数", index = 8)private Integer renewalNum;//投放qd@ExcelProperty(value = "投放qd", index = 9)private String qd;//创建人@ExcelProperty(value = "创建人", index = 10)private String createUser;//修改人@ExcelProperty(value = "修改人", index = 11)private String updateUser;//创建日期@ExcelProperty(value = "创建日期", index = 12)@DateTimeFormat("yyyy-MM-dd HH:mm:ss")@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",locale = "zh",timezone="GMT+8")private Date createTime;//修改日期@ExcelProperty(value = "修改日期", index = 13)@DateTimeFormat("yyyy-MM-dd HH:mm:ss")@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",locale = "zh",timezone="GMT+8")private Date updateTime;//@ExcelProperty(value = "签约商户", index = 14)private String signMerchant;}

这里要注意converter 的使用,例如:vipType在数据库中设定的是枚举值“1”,“2”,“3”,“4” 但是我们导出数据期望是其代表的含义描述,因此要转换,关注其convertToExcelData方法,转换如下:

package com.smy.cbs.easyexcel.write;import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.smy.cbs.enums.vip.VipType;/*** String and string converter** @author youlu*/
public class VipTypeStringConverter implements Converter<String> {@Overridepublic Class supportJavaTypeKey() {return String.class;}@Overridepublic CellDataTypeEnum supportExcelTypeKey() {return CellDataTypeEnum.STRING;}/*** 这里是读的时候会调用 不用管** @param cellData*            NotNull* @param contentProperty*            Nullable* @param globalConfiguration*            NotNull* @return*/@Overridepublic String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,GlobalConfiguration globalConfiguration) {return cellData.getStringValue();}/*** 这里是写的时候会调用 不用管** @param value*            NotNull* @param contentProperty*            Nullable* @param globalConfiguration*            NotNull* @return*/@Overridepublic CellData convertToExcelData(String value, ExcelContentProperty contentProperty,GlobalConfiguration globalConfiguration) {return new CellData(VipType.getVipTypeDescByCode(value));}
}
  1. service|Dao层实现
 @Overridepublic List<RenewalSignAdminResp> queryRenewalSignListForDownload(RenewalSignAdminReq req, boolean firstFlag, int pageSize) {return cbsRenewalSignInnerService.queryRenewalSignListForDownload(req, firstFlag, pageSize);}@Overridepublic List<RenewalSignAdminResp> queryRenewalSignListByCreateTimeAndId(RenewalSignAdminReq req, Date createTime, String startId) {return cbsRenewalSignInnerService.queryRenewalSignListByCreateTimeAndId(req,createTime, startId);}
  1. sql层查询
<select id="queryRenewalSignListForDownload" resultMap="signAdminMap">select<include refid="Base_Column_List" />from t_renewal_sign<where><choose><when test="firstFlag">and create_time &gt;= #{req.startCreateTime}</when><otherwise>and create_time &gt; #{req.startCreateTime}</otherwise></choose>and create_time &lt;= #{req.endCreateTime}and renewal_status = #{req.renewalStatus}<if test="req.custNo != null and req.custNo != ''">and cust_no = #{req.custNo}</if><if test="req.id != null and req.id != ''">and id = #{req.id}</if><if test="req.vipType != null and req.vipType != ''">and vip_type = #{req.vipType}</if></where>order by create_time , idlimit #{pageSize}</select>
  • firstFlag 用于区分是否是第一次查询
  • order by create_time , id 的排序可以用于解决慢sql问题。
    这个查询会存在漏数据的问题,因此引进下面这条sql专门查询在相同时间点内生成的数据
 <select id="queryRenewalSignListByCreateTimeAndId" resultMap="signAdminMap">select<include refid="Base_Column_List" />from t_renewal_sign<where>and create_time = #{createTime}and id &gt; #{startId}and renewal_status = #{req.renewalStatus}<if test="req.custNo != null and req.custNo != ''">and cust_no = #{req.custNo}</if><if test="req.id != null and req.id != ''">and id = #{req.id}</if><if test="req.vipType != null and req.vipType != ''">and vip_type = #{req.vipType}</if></where>
  • 这条sql的意义就是补偿,查询在相同时间点内生成的数据

这里解决了我们开头提到的所有问题。为什么呢?下节我们一起来分析下…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/668659.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AIGC实战——归一化流模型(Normalizing Flow Model)

AIGC实战——归一化流模型 0. 前言1. 归一化流模型1.1 归一化流模型基本原理1.2 变量变换1.3 雅可比行列式1.4 变量变换方程 2. RealNVP2.1 Two Moons 数据集2.2 耦合层2.3 通过耦合层传递数据2.4 堆叠耦合层2.5 训练 RealNVP 模型 3. RealNVP 模型分析4. 其他归一化流模型4.1 …

小红书种草图文怎么制作?纯干货

一篇优质的小红书种草图文&#xff0c;不仅能提升产品销量&#xff0c;还能为品牌带来广泛的关注。如何制作出高质量的小红书种草图文呢&#xff1f;本文伯乐网络传媒将为你一一揭晓。 一、小红书种草图文制作要点 1. 确定目标受众和主题 明确目标受众是谁&#xff0c;他们有何…

微服务入门篇:Nacos注册中心(Nacos安装,快速入门,多级存储,负载均衡,环境隔离,配置管理,热更新,集群搭建,nginx反向代理)

目录 1.Nacos安装1.官网下载2.解压到本地3.启动nacos 2.Nacos快速入门1.在父工程中导入nacos依赖2.给子项目添加客户端依赖3.修改对应服务的配置文件4.启动服务&#xff0c;查看nacos发现情况 3.Nacos服务多级存储模型4.NacosRule负载均衡5. 服务实例的权重设置6.环境隔离&…

PDF控件Spire.PDF for .NET【安全】演示:检测 PDF 文档是否受密码保护

Spire.PDF for .NET 是一款独立 PDF 控件&#xff0c;用于 .NET 程序中创建、编辑和操作 PDF 文档。使用 Spire.PDF 类库&#xff0c;开发人员可以新建一个 PDF 文档或者对现有的 PDF 文档进行处理&#xff0c;且无需安装 Adobe Acrobat。 E-iceblue 功能类库Spire 系列文档处…

2024数学建模美赛F题Reducing Illegal Wildlife Trade原创论文讲解(含完整python代码)

大家好呀&#xff0c;从发布赛题一直到现在&#xff0c;总算完成了数学建模美赛本次F题目非法野生动物贸易完整的成品论文。 本论文可以保证原创&#xff0c;保证高质量。绝不是随便引用一大堆模型和代码复制粘贴进来完全没有应用糊弄人的垃圾半成品论文。 F题论文共42页&…

Qt|实现时间选择小功能

在软件开发过程中&#xff0c;QtDesigner系统给出的控件很多时候都无法满足炫酷的效果&#xff0c;前一段时间需要用Qt实现选择时间的小功能&#xff0c;今天为大家分享一下&#xff01; 首先看一下时间效果吧&#xff01; 如果有需要继续往下看下去哟~ 功能 1&#xff1a;开…

聊聊PowerJob的AppInfoController

序 本文主要研究一下PowerJob的AppInfoController AppInfoController tech/powerjob/server/web/controller/AppInfoController.java RestController RequestMapping("/appInfo") RequiredArgsConstructor public class AppInfoController {private final AppInf…

SpringBoot过滤器获取请求的参数

一、背景 在项目开发过程中&#xff0c;需要对于某些接口统一处理。 这时候就需要获取请求的报文&#xff0c;再对获取的报文进行统一处理。 二、了解过滤器 首先了解一下过滤器拦截器的区别&#xff1a; JAVA中的拦截器、过滤器&#xff1a;https://blog.csdn.net/qq_38254…

‘javax.sql.DataSource‘ that could not be found的问题

报错信息如下&#xff1a; 2024-02-04 16:31:14.832 WARN 952 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDepen…

Leetcode—38. 外观数列【中等】

2024每日刷题&#xff08;111&#xff09; Leetcode—38. 外观数列 实现代码 class Solution { public:string countAndSay(int n) {string ans "1";while(--n) {string next;for(int i 0; i < ans.size(); i) {int cnt 1;char c ans[i];while(i 1 < an…

如何提高webpack构建速度以及优化前端性能

一.提高构建速度 1.多⼊⼝情况下&#xff0c;使⽤ CommonsChunkPlugin 来提取公共代码 2.通过 externals 配置来提取常⽤库 3.利⽤ DllPlugin 和 DllReferencePlugin 预编译资源模块 通过 DllPlugin 来对那些我们引⽤但是绝对不会修改的 npm 包来进⾏预 编译&#xff0c;再通过…

使用HTML、CSS和JavaScript来创建一个粒子效果,粒子会跟随鼠标点击位置生成

文章目录 一、粒子效果二、JavaScript三、HTML四、CSS五、热门文章 一、粒子效果 以下是一个简单的示例&#xff0c;使用HTML、CSS和JavaScript来创建一个粒子效果&#xff0c;粒子会跟随鼠标点击位置生成&#xff1a; <!DOCTYPE html> <html> <head><t…

【算法与数据结构】647、516、LeetCode回文子串+最长回文子序列

文章目录 一、647、回文子串二、516、最长回文子序列三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、647、回文子串 思路分析&#xff1a;判断一个字符串是否为回文串那么必须确定回文串的所在区间&#xff0c;而一维…

【RK3288 Android6 T8, 突然无声音问题排查】

文章目录 【RK3288 Android6 T8, 突然无声音问题排查】问题描述问题调查patch【RK3288 Android6 T8, 突然无声音问题排查】 问题描述 页面上方突然出现音量进度条,小铃铛图标显示静音状态,不再播报语音 手动去安卓设置内查看,小铃铛音量为0,手动恢复到有声音后继续执行…

Redis -- set集合

挑战自己&#xff0c;每天进步一点点&#xff0c;成就将属于不停止脚步的你。 目录 Redis集合&#xff1f; 集合基本命令 sadd smembers sismember scard spop srandmember smove srem 集合间操作 sinter sinterstore sunion sdiff sdiifstore Redis集合&#…

【Linux】EXT2文件系统 | 磁盘分区块组 | inode

文章目录 一、前言二、EXT2文件系统 - 逻辑存储结构&#x1f4be;分区&#xff08;Partition&#xff09;分区的概念每个分区的内容Linux下查询磁盘分区 &#x1f4be;块组&#xff08;Block Group&#xff09;磁盘格式化每个块组的内容1. Superblock&#xff08;超级块&#x…

106 C++ STL 标准模版库大局观,重要概念

一 C标准库 C standard Library。 只要你装了C编译器&#xff0c;那么这个 C标准库就会被自动的安装进来了。 为什么要装进来这个呢&#xff1f;主要是为了解决可复用问题。 C标准库给我们提供了大量的成熟的可使用的功能。因此用好 标准库&#xff0c;是一个合格的C程序员的…

【Delphi 基础知识 28】ListView控件的详细使用

文章目录 控件设置增加数据删除选中的行按标题删除读取某行某列内容修改某行某列内容清空内容设置焦点上下移动条目读出选中行信息点击正反排序每行item显示不一样的颜色 控件设置 ViewStyle 设为vsReportReadOnly 设为TrueGridLines 设为TrueRowSelect 设为True 增加数据 …

《Redis核心技术与实战》学习笔记0——开篇词 | 这样学Redis,才能技高一筹

开篇词 | 这样学Redis&#xff0c;才能技高一筹 文章目录 开篇词 | 这样学Redis&#xff0c;才能技高一筹为什么懂得了一个个技术点&#xff0c;却依然用不好 Redis&#xff1f; 作为键值数据库&#xff0c;Redis 的应用非常广泛&#xff0c;如果你是后端工程师&#xff0c;我猜…

Kubernetes的有状态应用示例:使用StatefulSet部署Cassandra

文章目录 环境概述准备为Cassandra创建headless service验证Cassandra StatefulSet修改Cassandra StatefulSet清理Cassandra容器环境变量参考 环境 RHEL 9.3Docker Community 24.0.7minikube v1.32.0 概述 本例展示了如何在Kubernetes上运行Apache Cassandra。Cassandra是一…