import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.SqlSession;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class LargeDataExportService {
private SqlSessionFactory sqlSessionFactory;
public void exportDataWithBatch(String filePath) {
// 1. 파일 초기화 (기존 파일이 있으면 덮어쓰기 위해 false, 이후 true로 append)
try (SqlSession session = sqlSessionFactory.openSession()) {
// MyBatis ResultHandler 구현
session.select("com.example.mapper.ProductMapper.selectLargeData", new ResultHandler<Map<String, Object>>() {
private final List<Map<String, Object>> batchList = new ArrayList<>(1000);
private boolean isFirstWrite = true;
@Override
public void handleResult(ResultContext<? extends Map<String, Object>> resultContext) {
batchList.add(resultContext.getResultObject());
// 1,000건이 쌓이면 파일에 씀
if (batchList.size() >= 1000) {
flushBatch(batchList, filePath, !isFirstWrite);
isFirstWrite = false;
batchList.clear();
}
}
// 마지막에 남은 데이터 처리 (예: 1000건이 안 되는 나머지)
public void flushRemaining() {
if (!batchList.isEmpty()) {
flushBatch(batchList, filePath, !isFirstWrite);
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
private void flushBatch(List<Map<String, Object>> data, String filePath, boolean append) {
// 2. BufferedWriter의 append 모드 활용
try (FileOutputStream fos = new FileOutputStream(filePath, append);
OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
BufferedWriter writer = new BufferedWriter(osw)) {
for (Map<String, Object> row : data) {
// 가공 로직 (압축 등) 수행 후 쓰기
String processedLine = processRow(row);
writer.write(processedLine);
writer.newLine();
}
writer.flush();
} catch (IOException e) {
throw new RuntimeException("파일 쓰기 중 오류 발생", e);
}
}
private String processRow(Map<String, Object> row) {
// 여기서 아까 논의한 Zstd/LZ4 압축 로직을 넣으시면 됩니다.
return row.get("ID").toString() + "," + row.get("NAME").toString();
}
}