Browse Source

测试

detached
zhangluping 5 months ago
parent
commit
59c32acf7c
  1. 36
      src/main/java/com/example/demo/controller/ExportExcelController.java
  2. 25
      src/main/java/com/example/demo/mapper/DetailYMapper.java
  3. 71
      src/main/java/com/example/demo/sevice/DataExportService.java
  4. 41
      src/main/java/com/example/demo/sevice/ExportExcelService.java

36
src/main/java/com/example/demo/controller/ExportExcelController.java

@ -0,0 +1,36 @@
package com.example.demo.controller;
import com.example.demo.sevice.DataExportService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
@RestController
@RequestMapping("/export")
@RequiredArgsConstructor
@Transactional
@Slf4j
@CrossOrigin
public class ExportExcelController {
@Autowired
private DataExportService dataExportService;
@PostMapping("/exportUserExcel")
public void exportUserExcel(HttpServletResponse response) {
try {
dataExportService.exportData(response);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("导出 Excel 文件失败", e);
}
}
}

25
src/main/java/com/example/demo/mapper/DetailYMapper.java

@ -1,11 +1,9 @@
package com.example.demo.mapper;
import com.example.demo.domain.entity.DetailY;
import com.example.demo.domain.entity.UserDetailExport;
import com.example.demo.domain.vo.DetailYgold;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.*;
import java.util.List;
@ -79,8 +77,8 @@ public interface DetailYMapper {
"<script>",
"SELECT",
" SUM(`recharge_coin`) AS 'sumR',",
" SUM(`task_coin`) AS 'sumT',",
" SUM(`free_coin`) AS 'sumF'",
" SUM(`recharge_coin`) AS 'sumT',",
" SUM(`recharge_coin`) AS 'sumF'",
"FROM",
"`detail_y`",
"<where>",
@ -91,4 +89,19 @@ public interface DetailYMapper {
"</script>"
})
DetailY getCount(DetailY detailY);
//导出数据的SQL
@Select({
"<script>",
"SELECT d.detaily_id,u.name,d.jwcode,u.area,d.consume_platform,d.update_type,d.recharge_coin,d.task_coin," +
"d.free_coin,d.create_admin,d.create_time",
"FROM detail_y d",
"LEFT JOIN user u on d.jwcode = u.jwcode ",
"ORDER BY detaily_id LIMIT #{offset}, #{pageSize}",
"</script>"
})
List<UserDetailExport> searchExport(@Param("offset") int offset, @Param("pageSize") int pageSize);
@Select("SELECT COUNT(*) FROM detail_y")
int getTotalCount();
}

71
src/main/java/com/example/demo/sevice/DataExportService.java

@ -0,0 +1,71 @@
package com.example.demo.sevice;
import com.example.demo.domain.entity.UserDetailExport;
import com.example.demo.mapper.DetailYMapper;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@Service
public class DataExportService {
// 设置线程池
private final ExecutorService executorService = Executors.newFixedThreadPool(3); // 使用10个线程的线程池
// 每次查询20w条数据
private static final int PAGE_SIZE = 100000;
@Autowired
private DetailYMapper detailYMapper;
@Autowired
private ExportExcelService exportExcelService;
public void exportData(HttpServletResponse response) throws IOException {
// 获取总记录数
int totalRecords = detailYMapper.getTotalCount(); // 获取总记录数
int totalPages = (totalRecords + PAGE_SIZE - 1) / PAGE_SIZE; // 计算总页
// 设置Excel响应头
exportExcelService.setExcelResponseProp(response, "userDetail");
// 创建一个集合用于收集所有查询结果
List<UserDetailExport> allData = new ArrayList<>();
List<Future<List<UserDetailExport>>> futures = new ArrayList<>();
// 使用多线程导出数据
for (int page = 0; page < totalPages; page++) {
final int currentPage = page;
futures.add(executorService.submit(() -> {
try {
return fetchData(currentPage, PAGE_SIZE); // 查询当前页的数据
} catch (Exception e) {
e.printStackTrace();
return new ArrayList<UserDetailExport>(); // 出错时返回空数据
}
}));
}
// 等待所有任务完成并收集结果
for (Future<List<UserDetailExport>> future : futures) {
try {
allData.addAll(future.get()); // 将每个线程的结果合并
} catch (Exception e) {
e.printStackTrace();
}
}
// 一次性写入Excel
exportExcelService.writeDataToSheet(response, allData, 0);
}
private List<UserDetailExport> fetchData(int page, int pageSize) {
int offset = page * pageSize; // 计算偏移量
return detailYMapper.searchExport(offset, pageSize); // 调用Mapper查询数据
}
}

41
src/main/java/com/example/demo/sevice/ExportExcelService.java

@ -0,0 +1,41 @@
package com.example.demo.sevice;
import com.alibaba.excel.EasyExcel;
import com.example.demo.domain.entity.UserDetailExport;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.List;
@Service
public class ExportExcelService {
// 设置响应头以导出 Excel 文件
public void setExcelResponseProp(HttpServletResponse response, String fileName) throws IOException {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".xlsx");
}
// 使用 EasyExcel 写入数据到 Excel
public void writeDataToSheet(HttpServletResponse response, List<UserDetailExport> allData, int sheetIndex) throws IOException {
int batchSize = 2000000; // 每次写入200w条
int totalDataSize = allData.size();
int currentSheetIndex = sheetIndex; // 用来区分不同的Sheet
for (int i = 0; i < totalDataSize; i += batchSize) {
int endIndex = Math.min(i + batchSize, totalDataSize);
List<UserDetailExport> batchData = allData.subList(i, endIndex);
// 每次写入一个新的 SheetSheet 名称使用 currentSheetIndex
EasyExcel.write(response.getOutputStream(), UserDetailExport.class)
.sheet("Sheet " + (currentSheetIndex + 1)) // 设置Sheet名称
.doWrite(batchData); // 写入当前批次的数据
currentSheetIndex++; // 增加 Sheet 索引
}
}
}
Loading…
Cancel
Save