У меня есть таблица с огромным количеством записей, скажем, почти 25 ГБ с более чем 1000 миллионами записей.Я хочу получить их с помощью Java и написать в CSV.Я думал об использовании потока java8, чтобы остановить вывод всего набора результатов в память, но все же я получаю ошибку пространства кучи Java.
try {
close=UncheckedCloseable.wrap(con);
pSt = con.prepareStatement("select * from "+this.tblName);
close=close.nest(pSt);
con.setAutoCommit(false);
pSt.setFetchSize(5000);
ResultSet resultSet = pSt.executeQuery();
close=close.nest(resultSet);
Stream<String> buffer = StreamSupport.stream(new Spliterators.AbstractSpliterator<String>(
Long.MAX_VALUE,Spliterator.ORDERED) {
@Override
public boolean tryAdvance(Consumer<? super String> action) {
try {
if(!resultSet.next()) return false;
action.accept(createRecord(resultSet));
return true;
} catch(SQLException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
}, false).onClose(close);
System.out.println(buffer.count());
Files.write(Paths.get(home.getAbsolutePath()+"/"+tblName+".csv"), (Iterable<String>)buffer::iterator);
}
private String createRecord(ResultSet resultSet) throws SQLException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
StringBuffer buffer = new StringBuffer();
int colCount = resultSet.getMetaData().getColumnCount();
while(resultSet.next()) {
for(int i=1; i<=colCount; i++) {
String columnName = resultSet.getMetaData().getColumnTypeName(i);
String getType = StringUtils.capitalize(columnName.toLowerCase());
Method methodName = getMethodName(resultSet,getType);
Object result = methodName.invoke(resultSet, i);
if(result == null || result.toString().equalsIgnoreCase("null")){
result = "";
}
if (result instanceof String) {
result = ((String) result).trim().replaceAll(",", "\\\\,").replace("\n", "").replace("\r", "");
}
buffer.append(result+",");
}
buffer.setLength(buffer.length()-1);
buffer.append("\n");
}
return buffer.toString();
}