#java #spring #spring-data #lazy-loading #junit4
#java #spring #spring-данные #отложенная загрузка #junit4
Вопрос:
Прежде чем описать свою проблему, я хочу сообщить вам, что я новичок в Spring.
Итак, здесь я просто помещаю свой пример кода, что я делаю для извлечения данных из БД с помощью JdbcTemplate :
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriver(new org.apache.derby.jdbc.EmbeddedDriver());
dataSource.setUrl("jdbc:derby:C:/Users/mypc/Downloads/db-derby-10.12.1.1-bin/db-derby-10.12.1.1-bin/demo/databases/toursdb;create=true");
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
List<Map<String, Object>> rows = jdbcTemplate.queryForList("select * from " tableName);
dataSource.getConnection().close();
System.out.println(rows);
Итак, здесь я помещаю весь свой результирующий набор в Map, а затем возвращаю его. Проблема в том, что она создает исключение из памяти кучи java для большого набора данных (как я упоминал выше, опубликованный код предназначен для примера).
Теперь я изменяю эту реализацию, используя RowCallbackHandler().
Итак, мой измененный код теперь
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriver(new org.apache.derby.jdbc.EmbeddedDriver());
dataSource.setUrl("jdbc:derby:C:/Users/mypc/Downloads/db-derby-10.12.1.1-bin/db-derby-10.12.1.1-bin/demo/databases/toursdb;create=true");
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.setFetchSize(200);
jdbcTemplate.query("select * from " tableName, new RowCallbackHandler() {
public void processRow(ResultSet rs) throws SQLException {
Map<String, Object> rowInMap = new HashMap<String, Object>();
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i ) {
rowInMap.put(rs.getMetaData().getColumnName(i), rs.getObject(i));
}
System.out.println(rowInMap);
}
});
dataSource.getConnection().close();
Но проблема в том, как использовать метод rowcallbackhandler из другого метода из другого класса, который будет лениво использовать данные, и, очевидно, он должен быть потокобезопасным. Он будет использоваться для тестирования JUnit.
Комментарии:
1.
consume data lazily
Я не думаю, что это означает то, что вы думаете. То, что вы, кажется, хотите, — это пакетирование, то есть потребляющий код извлекает данные пакетами некоторого фиксированного размера (например, 20, 50, 100 что угодно) и обрабатывает их порциями.2. да, точно, я хочу заполнить свою карту 20 данными, а затем обработать ее снова, чтобы восстановить часть набора результатов, и она заполнит карту следующими 20 данными
3. Я еще раз говорю, посмотрите на пакетную обработку с помощью шаблонов jdbc
4. Я изучаю это, но замечаю, что оно используется для обновления. мое требование — получение данных из БД, а не обновление БД.
5. разбиение на страницы может быть термином с большим количеством просмотров в Google.
Ответ №1:
Вы указываете драйверу jdbc извлекать строки по 200 и 200. Вот объяснение java-документа Statement class.
/**
* Gives the JDBC driver a hint as to the number of rows that should
* be fetched from the database when more rows are needed for
* <code>ResultSet</code> objects genrated by this <code>Statement</code>.
* If the value specified is zero, then the hint is ignored.
* The default value is zero.
*
* @param rows the number of rows to fetch
* @exception SQLException if a database access error occurs,
* this method is called on a closed <code>Statement</code> or the
* condition <code>rows >= 0</code> is not satisfied.
* @since 1.2
* @see #getFetchSize
*/
Вы не указываете отложенную загрузку или фильтрацию в своем запросе, вы извлекаете всю таблицу. Самый простой способ — использовать условие where для фильтрации ваших записей или использовать функцию разбивки на страницы.
Для oracle вы можете добавить «where rownum < 200» к вашему запросу.
Spring jdbc основан на выборке записей, сборе внутри коллекции и возврате. Поэтому, когда вы получаете свой список, это означает, что все данные извлекаются из базы данных, а оператор закрывается. Вы можете обработать свою запись внутри класса RowCallbackHandler, однако во время вашего процесса оператор базы данных и набор результатов будут открыты.
Комментарии:
1. Согласно вашему предложению, если я добавлю rownum для oracle или top для sql server, я не смогу получить все данные, но мне нужны все данные для проверки с моим ожидаемым.
2. итак, вам нужно отфильтровать свои данные с помощью предложения where в вашем sql. Кроме того, oracle rownum не гарантирует получение одних и тех же данных каждый раз.
3. Спасибо за ваши комментарии, но есть ли какой-либо способ вернуть фрагмент карты и проверить это, и если не найден желаемый результат, снова вызовите его и верните следующий фрагмент карты из того же результирующего набора, это похоже на возврат.