2010-02-01 2 views
2

Существует стол phonenumbers с двумя колонками: id и number. В таблице около half a million entries. База данных - MySQL.Обработка больших записей в приложении Java EE

Требование заключается в разработке простого приложения Java EE, подключенного к этой базе данных, которое позволяет пользователю загружать все значения number в comma separated style, следуя определенному URL-адресу.

Если мы получаем все значения в огромном String array и затем объединяем их (с запятой между всеми значениями) в String, а затем отправляем их пользователю, звучит ли это правильное решение?

Приложение не является общедоступным и будет использоваться ограниченным номером. людей.

+0

Имея полмиллиона разделенных запятыми, список значений не подходит для меня. Может быть, разделение новой строки в порядке, чтобы пользователь мог легко открыть этот файл в текстовом редакторе, если это необходимо. Но это зависит от того, как пользователи хотят использовать этот список значений. Не могли бы вы рассказать о требованиях пользователя? –

+0

CSV - это требование пользователя, потому что оно поддерживается MS Excel.Я не уверен, как они будут использовать его, вероятно, они будут использовать его для целей отчетности. – craftsman

+0

Карта CSV в столбцы в excel. Если у вас есть полмиллиона записей CSV, то как правильно будет работать в excel? Excel не имеет полмиллиона столбцов. Вы должны как пользователи, как они будут использовать его. Большую часть времени пользователи не уверены в своих требованиях. –

ответ

8

Лучше всего, чтобы не хранят данные в памяти Java в любом случае, а просто записывают полученные данные в ответ сразу по мере поступления данных. Вам также необходимо настроить драйвер JDBC MySQL для обслуживания набора результатов по строкам на Statement#setFetchSize() согласно MySQL JDBC driver documentation, иначе он будет хранить в памяти все это в памяти.

Предполагая, что вы знакомы с сервлетов, вот пример стартового который принимает все, что во внимание:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    response.setContentType("text/plain"); 
    response.setHeader("Content-Disposition", "attachment;filename=numbers.txt"); // Force download popup. 

    Connection connection = null; 
    Statement statement = null; 
    ResultSet resultSet = null; 
    Writer writer = response.getWriter(); 

    try { 
     connection = database.getConnection(); 
     statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); 
     statement.setFetchSize(Integer.MIN_VALUE); 
     resultSet = statement.executeQuery("SELECT number FROM phonenumbers"); 

     while (resultSet.next()) { 
      writer.write(resultSet.getString("number")); 
      if (!resultSet.isLast()) { 
       writer.write(","); 
      } 
     } 
    } catch (SQLException e) { 
     throw new ServletException("Query failed!", e); 
    } finally { 
     if (resultSet != null) try { resultSet.close; } catch (SQLException logOrIgnore) {} 
     if (statement != null) try { statement.close; } catch (SQLException logOrIgnore) {} 
     if (connection != null) try { connection.close; } catch (SQLException logOrIgnore) {} 
    } 
} 
+1

Я соглашаюсь «сразу же записать полученные данные в ответ, когда данные поступают» –

+0

Спасибо BalusC. Это именно то, что я хотел! – craftsman

1

Есть немного больше, чтобы правильно форматировать вывод CSV. Для генерации выходного файла было бы проще использовать существующую библиотеку, например this one.

Вы можете сгенерировать вывод в файл на диске (на веб-сервере), а затем перенаправить браузер в этот файл (с заданием cron или любым другим способом для очистки старых данных) или просто передать результат непосредственно пользователю ,

Если вы потоковом непосредственно быть уверены, и установить тип MIME к чему-то, что будет инициировать загрузку в браузере пользователя (например, текст/CSV или текст/разделители-запятые-значение)

+0

Я согласен, но хочу просто добавить http://supercsv.sourceforge.net/ в качестве бесплатной альтернативной библиотеки чтения/записи CSV. – fvu

+0

Я никогда раньше не работал с CSV. Можете ли вы рассказать, зачем нам нужна полная библиотека для этой цели, поскольку, по-видимому, это всего лишь запись значений, разделенных запятыми, с помощью Writer (как это видно на примере BalusC)? – craftsman

+0

В общем случае ваши данные могут содержать запятые, которые отбрасывают порядок полей, если они не обрабатываются должным образом, поскольку поля разделяются запятыми. Чтобы справиться с этим, вы указываете свои поля, которые могут содержать запятые. Кроме того, ваши данные могут содержать символы кавычек, которые отбрасывают цитирование, если оно не обрабатывается должным образом. Вам нужно избегать цитат. Вместо того, чтобы делать это вручную, мне легче использовать уже существующую библиотеку. Если вы на 100% уверены, что ваши данные никогда не будут содержать цитату или запятую (включая опечатки), вы можете просто написать свои поля, разделенные запятыми. –

0

При использовании Mysql 5.1 +, я бы просто использовать собственный синтаксис для дампа файла где-то и поток это в ответ Servlet.

SELECT a,b,a+b INTO OUTFILE '/tmp/result.txt' 
    FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' 
    LINES TERMINATED BY '\n' 
    FROM test_table; 

http://dev.mysql.com/doc/refman/5.1/en/select.html

Для многих записей, если вы все еще хотите использовать JDBC, вы можете попробовать следующее:

  • выборки количество записей выборки несколько записей (с помощью запроса ) и напишите их
  • , если вы достигнете номера записей в куске, вы получите еще один раз до вы достигаете максимума количество записей
+0

Предполагая, что веб-сервер использует файловую систему с БД. Во многих сценариях развертывания это не так. –

+0

Действительно, Eric J. –

+0

В моем случае DB и приложение работают на разных машинах. – craftsman