Backend Implementation:
1. Maven Dependencies
<!-- EasyExcel for data export -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.0.2</version>
</dependency>
2. Configuration Package
Create a config folder and add an ExcelExporter class. Replace the entity class with your own data model:
package com.cloud.config;
import com.cloud.domain.StockData;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import java.io.FileOutputStream;
import java.util.List;
@Slf4j
public class ExcelExporter {
public static void generateExcelReport(List<StockData> dataItems) {
// Starting row index
int currentRow = 0;
// Sheet counter
int sheetNumber = 1;
// Create workbook with streaming support
SXSSFWorkbook spreadsheet = new SXSSFWorkbook();
// Get the first sheet
Sheet dataSheet = spreadsheet.createSheet("Data_" + sheetNumber);
// Create header row
Row titleRow = dataSheet.createRow(0);
titleRow.createCell(1).setCellValue("ID");
titleRow.createCell(2).setCellValue("Symbol");
titleRow.createCell(3).setCellValue("Name");
titleRow.createCell(4).setCellValue("Exchange");
titleRow.createCell(5).setCellValue("Sector");
titleRow.createCell(6).setCellValue("Industry");
titleRow.createCell(7).setCellValue("Country");
titleRow.createCell(8).setCellValue("Currency");
titleRow.createCell(9).setCellValue("Listing Date");
// Populate data
for (StockData item : dataItems) {
if (currentRow >= 1048575) {
sheetNumber++;
dataSheet = spreadsheet.createSheet("Data_" + sheetNumber);
currentRow = 0;
// Recreate headers for new sheet
titleRow = dataSheet.createRow(0);
titleRow.createCell(1).setCellValue("ID");
titleRow.createCell(2).setCellValue("Symbol");
titleRow.createCell(3).setCellValue("Name");
titleRow.createCell(4).setCellValue("Exchange");
titleRow.createCell(5).setCellValue("Sector");
titleRow.createCell(6).setCellValue("Industry");
titleRow.createCell(7).setCellValue("Country");
titleRow.createCell(8).setCellValue("Currency");
titleRow.createCell(9).setCellValue("Listing Date");
}
Row dataRow = dataSheet.createRow(++currentRow);
dataRow.createCell(1).setCellValue(item.getId());
dataRow.createCell(2).setCellValue(item.getSymbol());
dataRow.createCell(3).setCellValue(item.getName());
dataRow.createCell(4).setCellValue(item.getExchange());
dataRow.createCell(5).setCellValue(item.getSector());
dataRow.createCell(6).setCellValue(item.getIndustry());
dataRow.createCell(7).setCellValue(item.getCountry());
dataRow.createCell(8).setCellValue(item.getCurrency());
dataRow.createCell(9).setCellValue(item.getListingDate());
}
// Define output path
String outputPath = "D:\\reports\\large_dataset.xlsx";
// Write to file
try (FileOutputStream fileOut = new FileOutputStream(outputPath)) {
spreadsheet.write(fileOut);
} catch (Exception e) {
e.printStackTrace();
log.error("Export error: ", e);
}
// Clean up resources
spreadsheet.dispose();
}
}
3. Controller Implementation
Add the fololwing method to your controller for handling large dataset exports using multithreading:
// Large dataset export endpoint
@GetMapping("/export-large-dataset")
public void handleLargeDatasetExport() {
// Using WorkStealingPool for IO-intensive operations (2n+1 cores)
ExecutorService threadPool = Executors.newWorkStealingPool(17);
try {
// Submit task to thread pool
Future<?> taskResult = threadPool.submit(() -> {
List<StockData> combinedData = new ArrayList<>();
// Fetch data in batches
List<StockData> batchOne = stockDataService.fetchBatchOne();
List<StockData> batchTwo = stockDataService.fetchBatchTwo();
List<StockData> batchThree = stockDataService.fetchBatchThree();
// Combine all batches
if (batchOne != null) combinedData.addAll(batchOne);
if (batchTwo != null) combinedData.addAll(batchTwo);
if (batchThree != null) combinedData.addAll(batchThree);
// Generate Excel report
ExcelExporter.generateExcelReport(combinedData);
});
// Wait for completion
taskResult.get();
} catch (Exception e) {
e.printStackTrace();
log.error("Export process error: ", e);
} finally {
// Shutdown thread pool
threadPool.shutdown();
}
}
4. Pagination SQL for Large Datasest
When dealing with millions of records, implement pagination in your SQL queries:
-- MySQL pagination
SELECT * FROM stock_data
LIMIT 100000 OFFSET 0;
-- Oracle pagination
SELECT * FROM (
SELECT a.*, ROWNUM rn FROM (
SELECT * FROM stock_data ORDER BY id
) a WHERE ROWNUM <= 100000
) WHERE rn > 0;
-- PostgreSQL pagination
SELECT * FROM stock_data
LIMIT 100000 OFFSET 0;
5. Annotations for Standard Excel Export
For regular Excel exports, add these annotations to your entity class fields:
@ExcelProperty("ID")
private Long id;
@ExcelProperty("Symbol")
private String symbol;
@ExcelProperty("Name")
private String name;
@ExcelProperty("Exchange")
private String exchange;
@ExcelProperty("Sector")
private String sector;
@ExcelProperty("Industry")
private String industry;
@ExcelProperty("Country")
private String country;
@ExcelProperty("Currency")
private String currency;
@ExcelProperty("Listing Date")
private String listingDate;