执行分页查询时的悲观锁定

时间:2018-12-13 16:40:13

标签: java sql jpa h2 jpql

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 DB,我试图手动执行类似的查询,因此:

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查询?

0 个答案:

没有答案