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