Пессимистическая блокировка при выполнении пагинационного запроса - PullRequest
0 голосов
/ 13 декабря 2018

tl; dr Как написать следующий запрос: SELECT * FROM T_BATCH_DATA WHERE ID IN (SELECT ID FROM T_BATCH_DATA OFFSET 5 ROWS FETCH FIRST 10 ROWS ONLY) FOR UPDATE ; с использованием JPQL ?

У меня запрос с именем JPQL: name=Foo.foo, query = "FROM Foo foo WHERE foo.modified<:date"

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

findFooByLastInteractionUpdate(int pageIndex, int noOfRecords, LocalDateTime retentionDate) 
{
    return entityManager.createNamedQuery("Foo.foo", Foo.class)
                .setParameter("date", date) //
                .setFirstResult(pageIndex * noOfRecords) //
                .setMaxResults(noOfRecords) //
                .setLockMode(LockModeType.PESSIMISTIC_WRITE) //
                .getResultList();
}

Модульный тест очень прост и выглядит так:

// given:
initializeDb();
LocalDateTime date = ...;

// when:
List<Foo> result = cut.findFooByLastInteractionUpdate(0, 3, date);

// then:
Assert.assertEquals(2, result.size());

А метод инициализации выглядит так:

initializeDb() {
    getEntityManager().createNativeQuery("INSERT INTO FOO (ID, ..., ..., ...) VALUES (1, ..., ..., ...)").executeUpdate();
}

Однако, когда я выполняю этот запрос, получаются следующие журналы: javax.persistence.PessimisticLockException: Exception [EclipseLink-4002 (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement ... FROM FOO WHERE (MODIFIED < ?) FOR UPDATE LIMIT[*] ? OFFSET ? "; SQL statement: SELECT FOO ... FROM FOO WHERE (MODIFIED < ?) FOR UPDATE LIMIT ? OFFSET ? [42000-196] Error Code: 42000

В руководстве по H2 я обнаружил, что код 42000 соответствует синтаксической ошибке.Имея доступ только к базе данных Oracle, я попытался выполнить подобный запрос вручную, поэтому:

SELECT * FROM FOO FOR UPDATE FETCH FIRST 10 ROWS ONLY OFFSET 5 ROWS;

, что приводит к ORA-02014.

Однако мне удалось переписатьзапрос выполняется успешно:

SELECT * FROM T_BATCH_DATA WHERE ID IN (SELECT ID FROM T_BATCH_DATA OFFSET 5 ROWS FETCH FIRST 10 ROWS ONLY) FOR UPDATE ;

Как переписать запрос JPQL?

...