Я имел опыт работы с огромными данными (почти 500 миллионов записей). Я просто использовал запрос PreparedStatement, ResultSet и, конечно, некоторые настройки буфера:
setFetchSize(int)
В моем случае я разделил программу на потоки, потому что огромная таблица была разбита (каждый поток обрабатывал один раздел), но я думаю, что это не ваш случай.
Бессмысленно получать данные через курсор. Я бы предпочел использовать представление базы данных или запрос SQL. Не используйте ORM для этой цели.
Согласно вашему комментарию, ваш лучший вариант - ограничить JDBC для выборки только определенного количества строк вместо выборки всех (это помогает начать обработку быстрее и не загружает всю таблицу в ResultSet). Сохраните ваши данные в коллекцию и запишите их в файл, используя BufferedWriter. Вы также можете воспользоваться многоядерным процессором, чтобы он работал в большем количестве потоков - например, первые извлеченные строки выполняются в 1 потоке, другие извлеченные строки во втором потоке. В случае создания потоков используйте синхронизированные коллекции и помните, что вы можете столкнуться с проблемой упорядочения.