Код: Выделить всё
@Transactional(readOnly = true)
public byte[] extractInformationAndGenerateExcel(String username, List comuniList) {
logger.info("------> " + comuniList.toString());
try (Stream contrattiEAttrezzatureStream = contrattiAttrezzatureRepository.getReportContrattiAttrezzature(username, comuniList);
ByteArrayOutputStream out = new ByteArrayOutputStream();
Workbook workbook = generateExcelService.generateExcelStream(REPORT_3_CONTRATTI, contrattiEAttrezzatureStream);)
{
workbook.write(out);
if (workbook instanceof SXSSFWorkbook) {
((SXSSFWorkbook) workbook).dispose();
}
return out.toByteArray();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Workbook generateExcelStream(String sheetName, Stream stream) {
logger.info("STARTING WRITING TO FILE: " + sheetName);
final int numberOfRowStoredInMemory = 100;
SXSSFWorkbook wb = new SXSSFWorkbook(numberOfRowStoredInMemory);
wb.setCompressTempFiles(Boolean.TRUE);
SXSSFSheet sheet = (SXSSFSheet) createSheet(sheetName, wb);
sheet.setRandomAccessWindowSize(100);
sheet.createFreezePane(0, 1);
AtomicInteger rowCount = new AtomicInteger(0);
AtomicReference[*]> fields = new AtomicReference(new ArrayList());
List headerNameList = new ArrayList();
Map fieldAlloweds = new HashMap();
Map>();
Map fieldGetterMethods = new HashMap();
stream.forEach(element -> {
if(rowCount.get() == 0) {
Class objectClass = element.getClass();
fields.set(getAllFields(objectClass));
for(Field field : fields.get()){
if (field.isAnnotationPresent(ExcludeFromExcel.class)) {
continue;
}
try {
Class fieldType = field.getType();
fieldTypes.put(field.getName(), fieldType);
fieldAlloweds.put(field.getName(), isFieldTypeAllowed(fieldType));
String headerName = getHeaderColumnName(field);
if(headerName != null){
headerNameList.add(headerName);
}
Method fieldGetterMethod = objectClass.getMethod(getFieldGetterMethodName(field.getName()));
fieldGetterMethods.put(field.getName(), fieldGetterMethod);
} catch (NoSuchMethodException e) {
// Field ignored
}
}
writeHeaderLine(headerNameList, wb, sheet);
}
Row row = sheet.createRow(rowCount.incrementAndGet());
int columnCount = 0;
for (Field field : fields.get()){
if (field.isAnnotationPresent(ExcludeFromExcel.class)) {
continue;
}
Method fieldGetter = fieldGetterMethods.get(field.getName());
if(fieldGetter != null && fieldAlloweds.get(field.getName())){
Object fieldValue = null;
try {
fieldValue = fieldGetter.invoke(element);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
Class fieldType = fieldTypes.get(field.getName());
if (fieldValue == null) {
fieldValue = "";
fieldType = String.class;
}
createCell(row, columnCount++, fieldValue, fieldType, null);
}
}
if (rowCount.get() % numberOfRowStoredInMemory == 0) {
try {
((SXSSFSheet) sheet).flushRows(numberOfRowStoredInMemory);
} catch (IOException e) {
e.printStackTrace();
}
}
});
return wb;
}
@Query(nativeQuery = true, value = "...My very Long Long query...")
@QueryHints(value = {
@QueryHint(name = "javax.persistence.query.timeout", value = "1200000"),
@QueryHint(name = "org.hibernate.readOnly", value = "true"),
@QueryHint(name = "org.hibernate.fetchSize", value = "50")
})
Stream getReportContrattiAttrezzature(@Param("username") String username, List comuni);
Моя ситуация с использованием VisualVM такова

Вот изображение профиля потока моего Java-приложения, показывающее время выполнения и состояние различных потоков во время операции создания отчета Excel:

< /p>
Вопросы:
- Правильно ли использовать Stream?
- Есть ли что-то, что я не учитываю?
- Как я могу повысить эффективность использования памяти с помощью моего подхода?
- Есть ли лучший вариант способ управления памятью с помощью Apache POI и больших наборов данных при использовании потоков?
Следует ли мне настроить конфигурацию SXSSFWorkbook или существует другая стратегия, которую мне следует рассмотреть, чтобы избежать исчерпания кучи?
Я провел тест, как предложено в комментариях, используя временный файл для записи данных и ничего не возвращая.
Это мой обновленный код:
Код: Выделить всё
public String extractInformationAndGenerateExcel(String username, List comuniList, String uniqueFileName) throws IOException {
logger.info("AVVIO PROCESSO ESTRAZIONE FILE PER I COMUNI: " + comuniList.toString());
Path tempFilePath = Files.createTempFile("temp_", ".txt");
try (Stream contrattiEAttrezzatureStream = contrattiAttrezzatureRepository.getReportContrattiAttrezzature(username, comuniList);
ByteArrayOutputStream out = new ByteArrayOutputStream();
BufferedWriter writer = Files.newBufferedWriter(tempFilePath, StandardOpenOption.WRITE)
)
{
logger.info("Start to write file??????");
contrattiEAttrezzatureStream.forEach(contratto -> {
try {
writer.write(contratto.toString());
writer.newLine();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
logger.info("Finish");
return "Finish?";
}catch (Exception e) {
throw new RuntimeException(e);
}finally {
// Opzionale: puoi eliminare il file temporaneo dopo l'upload se non ti serve più
if (tempFilePath != null && Files.exists(tempFilePath)) {
try {
Files.delete(tempFilePath);
} catch (IOException e) {
logger.error("Impossibile eliminare il file temporaneo", e);
}
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/790 ... ook-and-pr