Skip to content

Commit e133ba6

Browse files
fmbenhassinedarkmastermindz
authored andcommitted
Update SQLServer DDL script to use sequences instead of tables
Emulating sequences with tables causes deadlocks when running multiple jobs at the same time. Sequences have been supported in SQL Server since version 2012. This commit replaces the usage of tables to emulate sequences with real sequences. It also adds a new incrementer that is based on sequences instead of tables. Resolves spring-projects#1448
1 parent b2b5b48 commit e133ba6

File tree

5 files changed

+97
-7
lines changed

5 files changed

+97
-7
lines changed

spring-batch-core/src/main/resources/org/springframework/batch/core/schema-sqlserver.sql

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,6 @@ CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT (
7676
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
7777
) ;
7878

79-
CREATE TABLE BATCH_STEP_EXECUTION_SEQ (ID BIGINT IDENTITY);
80-
CREATE TABLE BATCH_JOB_EXECUTION_SEQ (ID BIGINT IDENTITY);
81-
CREATE TABLE BATCH_JOB_SEQ (ID BIGINT IDENTITY);
79+
CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ START WITH 0 MINVALUE 0 MAXVALUE 9223372036854775807 NO CACHE NO CYCLE;
80+
CREATE SEQUENCE BATCH_JOB_EXECUTION_SEQ START WITH 0 MINVALUE 0 MAXVALUE 9223372036854775807 NO CACHE NO CYCLE;
81+
CREATE SEQUENCE BATCH_JOB_SEQ START WITH 0 MINVALUE 0 MAXVALUE 9223372036854775807 NO CACHE NO CYCLE;

spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactory.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2006-2018 the original author or authors.
2+
* Copyright 2006-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -55,6 +55,7 @@
5555
* @author Lucas Ward
5656
* @author Michael Minella
5757
* @author Drummond Dawson
58+
* @author Mahmoud Ben Hassine
5859
* @see DatabaseType
5960
*/
6061
public class DefaultDataFieldMaxValueIncrementerFactory implements DataFieldMaxValueIncrementerFactory {
@@ -113,7 +114,7 @@ else if (databaseType == SQLITE) {
113114
return new SqliteMaxValueIncrementer(dataSource, incrementerName, incrementerColumnName);
114115
}
115116
else if (databaseType == SQLSERVER) {
116-
return new SqlServerMaxValueIncrementer(dataSource, incrementerName, incrementerColumnName);
117+
return new SqlServerSequenceMaxValueIncrementer(dataSource, incrementerName);
117118
}
118119
else if (databaseType == SYBASE) {
119120
return new SybaseMaxValueIncrementer(dataSource, incrementerName, incrementerColumnName);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.batch.item.database.support;
17+
18+
import javax.sql.DataSource;
19+
20+
import org.springframework.jdbc.support.incrementer.AbstractSequenceMaxValueIncrementer;
21+
22+
/**
23+
* Incrementer for SQL Server sequences.
24+
*
25+
* @author Mahmoud Ben Hassine
26+
* @since 5.0
27+
*/
28+
public class SqlServerSequenceMaxValueIncrementer extends AbstractSequenceMaxValueIncrementer {
29+
30+
public SqlServerSequenceMaxValueIncrementer(DataSource dataSource, String incrementerName) {
31+
super(dataSource, incrementerName);
32+
}
33+
34+
@Override
35+
protected String getSequenceQuery() {
36+
return "select next value for " + getIncrementerName();
37+
}
38+
}

spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactoryTests.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2006-2018 the original author or authors.
2+
* Copyright 2006-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@
3535
* @author Lucas Ward
3636
* @author Will Schipp
3737
* @author Drummond Dawson
38+
* @author Mahmoud Ben Hassine
3839
*/
3940
public class DefaultDataFieldMaxValueIncrementerFactoryTests extends TestCase {
4041

@@ -118,7 +119,7 @@ public void testPostgres(){
118119
}
119120

120121
public void testMsSqlServer(){
121-
assertTrue(factory.getIncrementer("sqlserver", "NAME") instanceof SqlServerMaxValueIncrementer);
122+
assertTrue(factory.getIncrementer("sqlserver", "NAME") instanceof SqlServerSequenceMaxValueIncrementer);
122123
}
123124

124125
public void testSybase(){
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.batch.item.database.support;
17+
18+
import javax.sql.DataSource;
19+
20+
import org.junit.Assert;
21+
import org.junit.Test;
22+
import org.junit.runner.RunWith;
23+
import org.mockito.Mock;
24+
import org.mockito.junit.MockitoJUnitRunner;
25+
26+
import static org.junit.Assert.assertEquals;
27+
28+
/**
29+
* @author Mahmoud Ben Hassine
30+
*/
31+
@RunWith(MockitoJUnitRunner.class)
32+
public class SqlServerSequenceMaxValueIncrementerTests {
33+
34+
@Mock
35+
private DataSource dataSource;
36+
37+
private SqlServerSequenceMaxValueIncrementer incrementer;
38+
39+
@Test
40+
public void testGetSequenceQuery() {
41+
// given
42+
this.incrementer = new SqlServerSequenceMaxValueIncrementer(this.dataSource, "BATCH_JOB_SEQ");
43+
44+
// when
45+
String sequenceQuery = this.incrementer.getSequenceQuery();
46+
47+
// then
48+
Assert.assertEquals("select next value for BATCH_JOB_SEQ", sequenceQuery);
49+
}
50+
}

0 commit comments

Comments
 (0)