diff --git a/pom.xml b/pom.xml
index eff0621b29..d556008a23 100644
--- a/pom.xml
+++ b/pom.xml
@@ -88,7 +88,7 @@
2.9.0
1.7.32
2.6.1
-
2.0.206
+ 2.1.210
3.36.0.3
10.14.2.0
2.19.0
diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/H2PagingQueryProvider.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/H2PagingQueryProvider.java
index 0fabb0d125..c371d67b11 100644
--- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/H2PagingQueryProvider.java
+++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/H2PagingQueryProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2006-2008 the original author or authors.
+ * Copyright 2006-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,22 +20,23 @@
* H2 implementation of a {@link org.springframework.batch.item.database.PagingQueryProvider} using database specific features.
*
* @author Dave Syer
+ * @author Henning Pöttker
* @since 2.1
*/
public class H2PagingQueryProvider extends AbstractSqlPagingQueryProvider {
@Override
public String generateFirstPageQuery(int pageSize) {
- return SqlPagingQueryUtils.generateTopSqlQuery(this, false, buildTopClause(pageSize));
+ return SqlPagingQueryUtils.generateLimitSqlQuery(this, false, buildLimitClause(pageSize));
}
@Override
public String generateRemainingPagesQuery(int pageSize) {
- return SqlPagingQueryUtils.generateTopSqlQuery(this, true, buildTopClause(pageSize));
+ return SqlPagingQueryUtils.generateLimitSqlQuery(this, true, buildLimitClause(pageSize));
}
- private String buildTopClause(int pageSize) {
- return new StringBuilder().append("TOP ").append(pageSize).toString();
+ private String buildLimitClause(int pageSize) {
+ return new StringBuilder().append("FETCH NEXT ").append(pageSize).append(" ROWS ONLY").toString();
}
@Override
@@ -44,8 +45,10 @@ public String generateJumpToItemQuery(int itemIndex, int pageSize) {
int offset = (page * pageSize) - 1;
offset = offset<0 ? 0 : offset;
- String topClause = new StringBuilder().append("LIMIT ").append(offset).append(" 1").toString();
- return SqlPagingQueryUtils.generateTopJumpToQuery(this, topClause);
+ String limitClause = new StringBuilder().append("OFFSET ")
+ .append(offset).append(" ROWS FETCH NEXT 1 ROWS ONLY")
+ .toString();
+ return SqlPagingQueryUtils.generateLimitJumpToQuery(this, limitClause);
}
}
diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/H2PagingQueryProviderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/H2PagingQueryProviderIntegrationTests.java
new file mode 100644
index 0000000000..eeaf8463b2
--- /dev/null
+++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/H2PagingQueryProviderIntegrationTests.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2022 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.batch.item.database.support;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+import javax.sql.DataSource;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import org.springframework.batch.item.database.Order;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+import org.springframework.jdbc.datasource.SimpleDriverDataSource;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.support.TransactionTemplate;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Henning Pöttker
+ */
+@RunWith(Parameterized.class)
+public class H2PagingQueryProviderIntegrationTests {
+
+ private final String compatibilityMode;
+
+ public H2PagingQueryProviderIntegrationTests(String compatibilityMode) {
+ this.compatibilityMode = compatibilityMode;
+ }
+
+ @Test
+ public void testQueryProvider() {
+ String connectionUrl = String.format("jdbc:h2:mem:%s;MODE=%s", UUID.randomUUID(), compatibilityMode);
+ DataSource dataSource = new SimpleDriverDataSource(new org.h2.Driver(), connectionUrl, "sa", "");
+ JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
+ PlatformTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
+ TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
+
+ transactionTemplate.executeWithoutResult(status -> {
+ jdbcTemplate.execute("CREATE TABLE TEST_TABLE (ID BIGINT NOT NULL, STRING VARCHAR(16) NOT NULL)");
+ jdbcTemplate.execute("INSERT INTO TEST_TABLE (ID, STRING) VALUES (1, 'Spring')");
+ jdbcTemplate.execute("INSERT INTO TEST_TABLE (ID, STRING) VALUES (2, 'Batch')");
+ jdbcTemplate.execute("INSERT INTO TEST_TABLE (ID, STRING) VALUES (3, 'Infrastructure')");
+
+ H2PagingQueryProvider queryProvider = new H2PagingQueryProvider();
+ queryProvider.setSelectClause("STRING");
+ queryProvider.setFromClause("TEST_TABLE");
+ Map sortKeys = new HashMap<>();
+ sortKeys.put("ID", Order.ASCENDING);
+ queryProvider.setSortKeys(sortKeys);
+
+ List firstPage = jdbcTemplate.queryForList(
+ queryProvider.generateFirstPageQuery(2),
+ String.class
+ );
+ assertArrayEquals("firstPage", new String[]{"Spring", "Batch"}, firstPage.toArray());
+
+ List secondPage = jdbcTemplate.queryForList(
+ queryProvider.generateRemainingPagesQuery(2),
+ String.class,
+ 2
+ );
+ assertArrayEquals("secondPage", new String[]{"Infrastructure"}, secondPage.toArray());
+
+ Integer secondItem = jdbcTemplate.queryForObject(
+ queryProvider.generateJumpToItemQuery(3, 2),
+ Integer.class
+ );
+ assertEquals(Integer.valueOf(2), secondItem);
+ });
+ }
+
+ @Parameters
+ public static List