Я пытаюсь реализовать пейджинг в спящем режиме, и я вижу странное поведение в спящем режиме. Я пробовал два запроса с одинаковым результатом
List<SomeData> dataList = (List<SomeData>) session.getCurrentSession()
.createQuery("from SomeData ad where ad.bar = :bar order by ad.id.name")
.setString("bar", foo)
.setFirstResult(i*PAGE_SIZE)
.setMaxResults(PAGE_SIZE)
.setFetchSize(PAGE_SIZE) // page_size is 1000 in my case
.list();
и
List<SomeData> datalist= (List<SomeData>) session.getCurrentSession()
.createCriteria(SomeData.class)
.addOrder(Order.asc("id.name"))
.add(Expression.eq("bar", foo))
.setFirstResult(i*PAGE_SIZE)
.setMaxResults(PAGE_SIZE)
.list();
У меня это в цикле for, и каждый раз, когда запускается этот запрос, время выполнения увеличивается. Первый вызов возвращается через 100 мс, второй через 150, а 5-й вызов занимает 2 секунды и т. Д.
Просматривая журналы сервера (MySql 5.1.36), я вижу, что запрос select действительно генерируется с помощью предложения LIMIT, но для каждой возвращаемой записи hibernate по какой-то причине также генерирует запрос на обновление. после первого результата он обновляет 1000 записей, после второго результата он обновляет 2000 записей и так далее. Таким образом, для страницы размером 1000 и 5 итераций цикла база данных получает 15 000 запросов (5K + 4K + 3K + 2K + 1K). Почему это происходит?
Я попытался сделать собственный запрос SQL, и он работал как положено. Запрос
List asins = (List) session.getCurrentSession()
.createSQLQuery("SELECT * FROM some_data where foo = :foo order by bar
LIMIT :from , :page")
.addScalar(..)
.setInteger("page", PAGE_SIZE)
.setInteger("from", (i*PAGE_SIZE))
... // set other params
.list();
Мой класс отображения имеет сеттеры / геттеры для объекта blob как
void setSomeBlob(Blob blob){
this.someByteArray = this.toByteArray(blob)
}
void Blob getSomeBlob(){
return Hibernate.createBlob(someByteArray)
}