Use strict H2 query syntax for paging query provider

Simplify tests a bit

Updated to snapshot dependencies

Updated test and to set the version of h2 to us boot bom.
This commit is contained in:
Henning Poettker
2022-01-02 02:15:06 +01:00
committed by Glenn Renfro
parent f74d38a47f
commit 102f4b7c35
11 changed files with 191 additions and 173 deletions

25
pom.xml
View File

@@ -94,6 +94,30 @@
<artifactId>spring-cloud-stream-test-support</artifactId>
<version>${spring-cloud-stream.version}</version>
</dependency>
<dependency> <groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.15-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-core</artifactId>
<version>${spring-batch.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-infrastructure</artifactId>
<version>${spring-batch.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-integration</artifactId>
<version>${spring-batch.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<version>${spring-batch.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
@@ -110,6 +134,7 @@
</modules>
<properties>
<spring-batch.version>4.3.5-SNAPSHOT</spring-batch.version>
<spring-cloud-stream.version>3.2.1</spring-cloud-stream.version>
<spring-cloud-deployer.version>2.7.0</spring-cloud-deployer.version>
<spring-cloud-deployer-local.version>2.7.0

View File

@@ -150,7 +150,8 @@ public class JdbcBatchItemWriterAutoConfigurationTests {
return applicationContextRunner.withPropertyValues("spring.batch.job.jobName=job",
"spring.batch.job.stepName=step1", "spring.batch.job.chunkSize=5",
"spring.batch.job.jdbcbatchitemwriter.name=fooWriter",
"spring.batch.job.jdbcbatchitemwriter.sql=INSERT INTO item (item_name) VALUES (:item_name)");
"spring.batch.job.jdbcbatchitemwriter.sql=INSERT INTO item (item_name) VALUES (:item_name)",
"spring.batch.jdbc.initialize-schema=always");
}
private void validateResultAndBean(ApplicationContext context) {

View File

@@ -100,7 +100,8 @@ public class JdbcCursorItemReaderAutoConfigurationTests {
.withPropertyValues("spring.batch.job.jobName=integrationJob",
"spring.batch.job.stepName=step1", "spring.batch.job.chunkSize=5",
"spring.batch.job.jdbccursoritemreader.name=fooReader",
"spring.batch.job.jdbccursoritemreader.sql=select item_name from item");
"spring.batch.job.jdbccursoritemreader.sql=select item_name from item",
"spring.batch.jdbc.initialize-schema=always");
applicationContextRunner.run((context) -> {
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
@@ -137,7 +138,8 @@ public class JdbcCursorItemReaderAutoConfigurationTests {
.withPropertyValues("spring.batch.job.jobName=rowMapperJob",
"spring.batch.job.stepName=step1", "spring.batch.job.chunkSize=5",
"spring.batch.job.jdbccursoritemreader.name=fooReader",
"spring.batch.job.jdbccursoritemreader.sql=select * from item");
"spring.batch.job.jdbccursoritemreader.sql=select * from item",
"spring.batch.jdbc.initialize-schema=always");
applicationContextRunner.run((context) -> {
JobLauncher jobLauncher = context.getBean(JobLauncher.class);

View File

@@ -2,82 +2,3 @@ CREATE TABLE IF NOT EXISTS item
(
item_name varchar(55)
);
CREATE TABLE IF NOT EXISTS BATCH_JOB_INSTANCE (
JOB_INSTANCE_ID BIGINT IDENTITY NOT NULL PRIMARY KEY ,
VERSION BIGINT ,
JOB_NAME VARCHAR(100) NOT NULL,
JOB_KEY VARCHAR(32) NOT NULL,
constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY)
) ;
CREATE TABLE IF NOT EXISTS BATCH_JOB_EXECUTION (
JOB_EXECUTION_ID BIGINT IDENTITY NOT NULL PRIMARY KEY ,
VERSION BIGINT ,
JOB_INSTANCE_ID BIGINT NOT NULL,
CREATE_TIME TIMESTAMP NOT NULL,
START_TIME TIMESTAMP DEFAULT NULL ,
END_TIME TIMESTAMP DEFAULT NULL ,
STATUS VARCHAR(10) ,
EXIT_CODE VARCHAR(2500) ,
EXIT_MESSAGE VARCHAR(2500) ,
LAST_UPDATED TIMESTAMP,
JOB_CONFIGURATION_LOCATION VARCHAR(2500) NULL,
constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ;
CREATE TABLE IF NOT EXISTS BATCH_JOB_EXECUTION_PARAMS (
JOB_EXECUTION_ID BIGINT NOT NULL ,
TYPE_CD VARCHAR(6) NOT NULL ,
KEY_NAME VARCHAR(100) NOT NULL ,
STRING_VAL VARCHAR(250) ,
DATE_VAL TIMESTAMP DEFAULT NULL ,
LONG_VAL BIGINT ,
DOUBLE_VAL DOUBLE PRECISION ,
IDENTIFYING CHAR(1) NOT NULL ,
constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ;
CREATE TABLE IF NOT EXISTS BATCH_STEP_EXECUTION (
STEP_EXECUTION_ID BIGINT IDENTITY NOT NULL PRIMARY KEY ,
VERSION BIGINT NOT NULL,
STEP_NAME VARCHAR(100) NOT NULL,
JOB_EXECUTION_ID BIGINT NOT NULL,
START_TIME TIMESTAMP NOT NULL ,
END_TIME TIMESTAMP DEFAULT NULL ,
STATUS VARCHAR(10) ,
COMMIT_COUNT BIGINT ,
READ_COUNT BIGINT ,
FILTER_COUNT BIGINT ,
WRITE_COUNT BIGINT ,
READ_SKIP_COUNT BIGINT ,
WRITE_SKIP_COUNT BIGINT ,
PROCESS_SKIP_COUNT BIGINT ,
ROLLBACK_COUNT BIGINT ,
EXIT_CODE VARCHAR(2500) ,
EXIT_MESSAGE VARCHAR(2500) ,
LAST_UPDATED TIMESTAMP,
constraint JOB_EXEC_STEP_FK foreign key (JOB_EXECUTION_ID)
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ;
CREATE TABLE IF NOT EXISTS BATCH_STEP_EXECUTION_CONTEXT (
STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY,
SHORT_CONTEXT VARCHAR(2500) NOT NULL,
SERIALIZED_CONTEXT LONGVARCHAR ,
constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID)
references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID)
) ;
CREATE TABLE IF NOT EXISTS BATCH_JOB_EXECUTION_CONTEXT (
JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY,
SHORT_CONTEXT VARCHAR(2500) NOT NULL,
SERIALIZED_CONTEXT LONGVARCHAR ,
constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID)
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ;
CREATE SEQUENCE IF NOT EXISTS BATCH_STEP_EXECUTION_SEQ;
CREATE SEQUENCE IF NOT EXISTS BATCH_JOB_EXECUTION_SEQ;
CREATE SEQUENCE IF NOT EXISTS BATCH_JOB_SEQ;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 the original author or authors.
* Copyright 2016-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.
@@ -23,15 +23,17 @@ import org.springframework.data.domain.Pageable;
* H2 implementation of a {@link PagingQueryProvider} using database specific features.
*
* @author Glenn Renfro
* @author Henning Pöttker
*/
public class H2PagingQueryProvider extends AbstractSqlPagingQueryProvider {
@Override
public String getPageQuery(Pageable pageable) {
String topClause = new StringBuilder().append("LIMIT ")
.append(pageable.getOffset()).append(" ").append(pageable.getPageSize())
String limitClause = new StringBuilder().append("OFFSET ")
.append(pageable.getOffset()).append(" ROWS FETCH NEXT ")
.append(pageable.getPageSize()).append(" ROWS ONLY")
.toString();
return SqlPagingQueryUtils.generateTopJumpToQuery(this, topClause);
return SqlPagingQueryUtils.generateLimitJumpToQuery(this, limitClause);
}
}

View File

@@ -133,12 +133,6 @@ public class SimpleTaskAutoConfigurationTests {
.withPropertyValues("spring.cloud.task.tablePrefix=foobarless");
verifyExceptionThrownDefaultExecutable(ApplicationContextException.class,
"Failed to start " + "bean 'taskLifecycleListener'; nested exception is "
+ "org.springframework.dao.DataAccessResourceFailureException: "
+ "Could not obtain sequence value; nested exception is org.h2.jdbc.JdbcSQLSyntaxErrorException: "
+ "Syntax error in SQL statement \"SELECT FOOBARLESSSEQ.NEXTVAL FROM[*] DUAL\"; "
+ "expected \"identifier\"; SQL statement:\n"
+ "select foobarlessSEQ.nextval from dual [42001-200]",
applicationContextRunner);
}
@@ -176,6 +170,17 @@ public class SimpleTaskAutoConfigurationTests {
}
public void verifyExceptionThrownDefaultExecutable(Class classToCheck, ApplicationContextRunner applicationContextRunner) {
Executable executable = () -> {
applicationContextRunner.run((context) -> {
Throwable expectedException = context.getStartupFailure();
assertThat(expectedException).isNotNull();
throw expectedException;
});
};
assertThatExceptionOfType(classToCheck).isThrownBy(executable::execute);
}
public void verifyExceptionThrownDefaultExecutable(Class classToCheck, String message,
ApplicationContextRunner applicationContextRunner) {
Executable executable = () -> {

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2022-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.cloud.task.repository;
import java.util.UUID;
import javax.sql.DataSource;
import org.h2.engine.Mode.ModeEnum;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.cloud.task.configuration.EnableTask;
import org.springframework.cloud.task.configuration.SimpleTaskAutoConfiguration;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Henning Pöttker
*/
class H2TaskRepositoryIntegrationTests {
@ParameterizedTest
@EnumSource(ModeEnum.class)
void testTaskRepository(ModeEnum mode) {
String connectionUrl = String.format("jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1;MODE=%s", UUID.randomUUID(), mode);
ApplicationContextRunner applicationContextRunner = new ApplicationContextRunner()
.withUserConfiguration(TestConfiguration.class)
.withBean(DataSource.class,
() -> new SimpleDriverDataSource(new org.h2.Driver(), connectionUrl, "sa", ""));
applicationContextRunner.run((context -> {
TaskExplorer taskExplorer = context.getBean(TaskExplorer.class);
assertThat(taskExplorer.getTaskExecutionCount()).isOne();
}));
}
@EnableTask
@ImportAutoConfiguration(SimpleTaskAutoConfiguration.class)
static class TestConfiguration {
}
}

View File

@@ -35,7 +35,7 @@ import static org.assertj.core.api.Assertions.fail;
*
* @author Gunnar Hillert
*/
public class BaseTaskExecutionDaoTestCases {
public abstract class BaseTaskExecutionDaoTestCases {
protected TaskExecutionDao dao;

View File

@@ -0,0 +1,81 @@
/*
* Copyright 2022-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.cloud.task.repository.database.support;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.sql.DataSource;
import org.h2.engine.Mode.ModeEnum;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.springframework.batch.item.database.Order;
import org.springframework.data.domain.PageRequest;
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.assertj.core.api.Assertions.assertThat;
/**
* @author Henning Pöttker
*/
class H2PagingQueryProviderTests {
@ParameterizedTest
@EnumSource(ModeEnum.class)
void testH2PagingQueryProvider(ModeEnum mode) {
String connectionUrl = String.format("jdbc:h2:mem:%s;MODE=%s", UUID.randomUUID(), mode);
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(10) NOT NULL)");
jdbcTemplate.execute("INSERT INTO TEST_TABLE (ID, STRING) VALUES (1, 'Spring')");
jdbcTemplate.execute("INSERT INTO TEST_TABLE (ID, STRING) VALUES (2, 'Cloud')");
jdbcTemplate.execute("INSERT INTO TEST_TABLE (ID, STRING) VALUES (3, 'Task')");
H2PagingQueryProvider queryProvider = new H2PagingQueryProvider();
queryProvider.setSelectClause("STRING");
queryProvider.setFromClause("TEST_TABLE");
Map<String, Order> sortKeys = new HashMap<>();
sortKeys.put("ID", Order.ASCENDING);
queryProvider.setSortKeys(sortKeys);
List<String> firstPage = jdbcTemplate.queryForList(
queryProvider.getPageQuery(PageRequest.of(0, 2)),
String.class
);
assertThat(firstPage).containsExactly("Spring", "Cloud");
List<String> secondPage = jdbcTemplate.queryForList(
queryProvider.getPageQuery(PageRequest.of(1, 2)),
String.class
);
assertThat(secondPage).containsExactly("Task");
});
}
}

View File

@@ -2,3 +2,4 @@ spring.application.name=Single Step Batch Job
spring.batch.job.jobName=job
spring.batch.job.stepName=step1
spring.batch.job.chunkSize=5
spring.batch.jdbc.initialize-schema=always

View File

@@ -14,83 +14,3 @@ INSERT INTO item_sample (item_name) VALUES ('baz');
INSERT INTO item_sample (item_name) VALUES ('boo');
INSERT INTO item_sample (item_name) VALUES ('qux');
INSERT INTO item_sample (item_name) VALUES ('Job');
CREATE TABLE BATCH_JOB_INSTANCE (
JOB_INSTANCE_ID BIGINT IDENTITY NOT NULL PRIMARY KEY ,
VERSION BIGINT ,
JOB_NAME VARCHAR(100) NOT NULL,
JOB_KEY VARCHAR(32) NOT NULL,
constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY)
) ;
CREATE TABLE BATCH_JOB_EXECUTION (
JOB_EXECUTION_ID BIGINT IDENTITY NOT NULL PRIMARY KEY ,
VERSION BIGINT ,
JOB_INSTANCE_ID BIGINT NOT NULL,
CREATE_TIME TIMESTAMP NOT NULL,
START_TIME TIMESTAMP DEFAULT NULL ,
END_TIME TIMESTAMP DEFAULT NULL ,
STATUS VARCHAR(10) ,
EXIT_CODE VARCHAR(2500) ,
EXIT_MESSAGE VARCHAR(2500) ,
LAST_UPDATED TIMESTAMP,
JOB_CONFIGURATION_LOCATION VARCHAR(2500) NULL,
constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ;
CREATE TABLE BATCH_JOB_EXECUTION_PARAMS (
JOB_EXECUTION_ID BIGINT NOT NULL ,
TYPE_CD VARCHAR(6) NOT NULL ,
KEY_NAME VARCHAR(100) NOT NULL ,
STRING_VAL VARCHAR(250) ,
DATE_VAL TIMESTAMP DEFAULT NULL ,
LONG_VAL BIGINT ,
DOUBLE_VAL DOUBLE PRECISION ,
IDENTIFYING CHAR(1) NOT NULL ,
constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ;
CREATE TABLE BATCH_STEP_EXECUTION (
STEP_EXECUTION_ID BIGINT IDENTITY NOT NULL PRIMARY KEY ,
VERSION BIGINT NOT NULL,
STEP_NAME VARCHAR(100) NOT NULL,
JOB_EXECUTION_ID BIGINT NOT NULL,
START_TIME TIMESTAMP NOT NULL ,
END_TIME TIMESTAMP DEFAULT NULL ,
STATUS VARCHAR(10) ,
COMMIT_COUNT BIGINT ,
READ_COUNT BIGINT ,
FILTER_COUNT BIGINT ,
WRITE_COUNT BIGINT ,
READ_SKIP_COUNT BIGINT ,
WRITE_SKIP_COUNT BIGINT ,
PROCESS_SKIP_COUNT BIGINT ,
ROLLBACK_COUNT BIGINT ,
EXIT_CODE VARCHAR(2500) ,
EXIT_MESSAGE VARCHAR(2500) ,
LAST_UPDATED TIMESTAMP,
constraint JOB_EXEC_STEP_FK foreign key (JOB_EXECUTION_ID)
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ;
CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT (
STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY,
SHORT_CONTEXT VARCHAR(2500) NOT NULL,
SERIALIZED_CONTEXT LONGVARCHAR ,
constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID)
references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID)
) ;
CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT (
JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY,
SHORT_CONTEXT VARCHAR(2500) NOT NULL,
SERIALIZED_CONTEXT LONGVARCHAR ,
constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID)
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ;
CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ;
CREATE SEQUENCE BATCH_JOB_EXECUTION_SEQ;
CREATE SEQUENCE BATCH_JOB_SEQ;