Primefaces LazyDataModel: правильный способ использования

У меня огромный список объектов, каждый из которых содержит количество изображений. Я хочу использовать ленивую загрузку, чтобы получить их частично. И я хочу понять, как использовать LazyDataModel и как это работает.

Изначально я думал, что мне нужно сохранять только идентификаторы потенциально извлеченных объектов внутри LazyDataModel. И когда вызывается метод load() - я должен получить изображения из БД и заменить источник данных извлеченными данными. Поэтому каждый раз, когда я хочу загрузить больше данных, я запускаю запрос.

private List<MyEntity> datasource; // contains only ids of MyEntity

@Override
public List<MyEntity> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String,Object> filters) {
    //rowCount
    int dataSize = datasource.size();
    this.setRowCount(dataSize);

    //get listOfIdToFetch

    //paginate
    datasource = datasource.addAll(myJpaRepository.findByIds(listOfIdToFetch));
    return datasource;
}

Я не мог заставить это работать, потому что основные лица использовали метод lock() и выдавали исключение, когда новая часть данных должна была быть загружена:

org.springframework.webflow.conversation.impl.LockTimeoutException: невозможно получить блокировку разговора через 30 секунд

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

private List<MyEntity> datasource; // contains all images of all records
@Override
public List<MyEntity> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String,Object> filters) {
    //rowCount
    int dataSize = datasource.size();
    this.setRowCount(dataSize);

    //paginate
    return datasource.subList(first, first + pageSize);
}

Я хочу понять, как LazyDataModel работает и увеличивает производительность. Если правильный способ использования этого подхода - извлечь все данные из БД и сохранить их в источнике данных. Сохраняет ли Primefaces эти данные на сервере и сбрасывает их по частям? Что если результат sql содержит тысячи изображений, следует ли мне искать другой подход и устанавливать лимит найденных записей? Как добиться лучшего увеличения производительности при отложенной загрузке? Или, возможно, первоначальный подход правильный, и я должен выяснить, почему возникает эта ошибка?

1 ответ

Решение

Хорошо, я наконец сделал это, и идея, что я должен выполнять запрос каждый раз при запуске метода load(), была правильной.

Проблемы, с которыми я сталкиваюсь:

  1. Если я просто возвращаю результат моего запроса, метод load() запускается только один раз, и я не могу загрузить больше данных. Поэтому я использую фиктивный подсписок (0, chunkSize).
  2. Я не смог @Autowire моего хранилища, у меня было исключение, сказав, что некоторые объекты не сериализованы. Но я мог бы использовать EntityManager, и это то, что я сделал.

Исходный код:

private List<MyEntity> datasource; // contains only ids

@Override
public List<MyEntity> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String,Object> filters) {
        StringBuilder queryText = new StringBuilder("select ...");
        List<MyEntity> list;

        //paginate
        if(datasource.size() > pageSize) {
            try {
                list = new ArrayList<>(datasource.subList(first, first + pageSize));
            }
            catch(IndexOutOfBoundsException e) {
                list = new ArrayList<>(datasource.subList(first, first + (datasource.size() % pageSize)));
            }
        }
        else {
            list = new ArrayList<>(datasource);
        }

        boolean setComa = false;
        for (MyEntity a: list) {
            if (setComa) {
                queryText.append(","+a.getId());
            } else {
                queryText.append(a.getId());
                setComa = true;
            }
        }
        queryText.append(")");
        Query q = em.createQuery(queryText.toString());
        list = q.getResultList();
        return list.subList(0, list.size());
}

ОБНОВЛЕНИЕ ОГРАНИЧЕНИЯ:

@Override
public List<MyEntity> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String,Object> filters) {

    List<MyEntity> list;

    Query q = em.createQuery(this.queryText);

    // Paginate
    q.setFirstResult(first); 
    q.setMaxResults(pageSize); 
    list = query.getResultList();

    return list.subList(0,list.size());
}
Другие вопросы по тегам