Skip to content

Commit 4f6ecf5

Browse files
THD-Thomas-Langschauder
authored andcommitted
DATAJDBC-258 - Integration test support for MS SQL Server added.
This adds MS-SQL-Server via Testcontainers to the set of databases available for integration testing. For this purpose it accepts the EULA of MS SQL Server. Failing tests are ignored to be fixed in separate issues. Original pull request: #98.
1 parent c47cd08 commit 4f6ecf5

21 files changed

+189
-18
lines changed

pom.xml

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<modelVersion>4.0.0</modelVersion>
66

7-
<groupId>org.springframework.data</groupId>
7+
<groupId>org.springframework.data</groupId>
88
<artifactId>spring-data-relational-parent</artifactId>
99
<version>1.1.0.BUILD-SNAPSHOT</version>
1010
<packaging>pom</packaging>
@@ -29,12 +29,14 @@
2929
<degraph-check.version>0.1.4</degraph-check.version>
3030

3131
<hsqldb.version>2.2.8</hsqldb.version>
32+
<mssql.verion>7.0.0.jre8</mssql.verion>
3233
<mybatis.version>3.4.6</mybatis.version>
3334
<mybatis-spring.version>1.3.2</mybatis-spring.version>
3435
<mysql-connector-java.version>5.1.41</mysql-connector-java.version>
3536
<postgresql.version>42.0.0</postgresql.version>
3637
<mariadb-java-client.version>2.2.3</mariadb-java-client.version>
37-
<testcontainers.version>1.7.3</testcontainers.version>
38+
<testcontainers.version>1.9.1</testcontainers.version>
39+
3840
</properties>
3941

4042
<inceptionYear>2017</inceptionYear>
@@ -164,6 +166,24 @@
164166
</systemPropertyVariables>
165167
</configuration>
166168
</execution>
169+
<execution>
170+
<id>mssql-test</id>
171+
<phase>test</phase>
172+
<goals>
173+
<goal>test</goal>
174+
</goals>
175+
<configuration>
176+
<includes>
177+
<include>**/*IntegrationTests.java</include>
178+
</includes>
179+
<excludes>
180+
<exclude>**/*HsqlIntegrationTests.java</exclude>
181+
</excludes>
182+
<systemPropertyVariables>
183+
<spring.profiles.active>mssql</spring.profiles.active>
184+
</systemPropertyVariables>
185+
</configuration>
186+
</execution>
167187
</executions>
168188
</plugin>
169189
</plugins>
@@ -177,7 +197,7 @@
177197
<plugin>
178198
<groupId>org.apache.maven.plugins</groupId>
179199
<artifactId>maven-surefire-plugin</artifactId>
180-
<version>2.12</version>
200+
<version>2.22.1</version>
181201
</plugin>
182202
<plugin>
183203
<groupId>org.apache.maven.plugins</groupId>

spring-data-jdbc/pom.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,13 @@
158158
<scope>test</scope>
159159
</dependency>
160160

161+
<dependency>
162+
<groupId>com.microsoft.sqlserver</groupId>
163+
<artifactId>mssql-jdbc</artifactId>
164+
<version>${mssql.verion}</version>
165+
<scope>test</scope>
166+
</dependency>
167+
161168
<dependency>
162169
<groupId>de.schauderhaft.degraph</groupId>
163170
<artifactId>degraph-check</artifactId>
@@ -192,6 +199,13 @@
192199
<scope>test</scope>
193200
</dependency>
194201

202+
<dependency>
203+
<groupId>org.testcontainers</groupId>
204+
<artifactId>mssqlserver</artifactId>
205+
<version>${testcontainers.version}</version>
206+
<scope>test</scope>
207+
</dependency>
208+
195209
</dependencies>
196210

197211
</project>

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.stream.Collectors;
2525
import java.util.stream.StreamSupport;
2626

27+
import org.springframework.dao.DataRetrievalFailureException;
2728
import org.springframework.dao.EmptyResultDataAccessException;
2829
import org.springframework.dao.InvalidDataAccessApiUsageException;
2930
import org.springframework.data.jdbc.support.JdbcUtil;
@@ -48,6 +49,7 @@
4849
*
4950
* @author Jens Schauder
5051
* @author Mark Paluch
52+
* @author Thomas Lang
5153
*/
5254
@RequiredArgsConstructor
5355
public class DefaultDataAccessStrategy implements DataAccessStrategy {
@@ -319,20 +321,31 @@ private static <S, ID> boolean isIdPropertyNullOrScalarZero(@Nullable ID idValue
319321

320322
private <S> Object getIdFromHolder(KeyHolder holder, RelationalPersistentEntity<S> persistentEntity) {
321323

322-
try {
323-
// MySQL just returns one value with a special name
324-
return holder.getKey();
325-
} catch (InvalidDataAccessApiUsageException e) {
326-
// Postgres returns a value for each column
327-
Map<String, Object> keys = holder.getKeys();
328-
329-
if (keys == null || persistentEntity.getIdProperty() == null) {
330-
return null;
331-
}
332-
333-
return keys.get(persistentEntity.getIdColumn());
334-
}
335-
}
324+
try {
325+
// MySQL just returns one value with a special name
326+
return holder.getKey();
327+
} catch (InvalidDataAccessApiUsageException e) {
328+
// Postgres returns a value for each column
329+
Map<String, Object> keys = holder.getKeys();
330+
331+
if (keys == null || persistentEntity.getIdProperty() == null) {
332+
return null;
333+
}
334+
335+
return keys.get(persistentEntity.getIdColumn());
336+
} catch (DataRetrievalFailureException e) {
337+
// thomas.lang@th-deg.de
338+
// mssql causes org.springframework.dao.DataRetrievalFailureException:
339+
// The generated key is not of a supported numeric type. Unable to cast [null] to [java.lang.Number]
340+
// see what happens here
341+
342+
Map<String, Object> keys = holder.getKeys();
343+
if (keys == null || persistentEntity.getIdProperty() == null) {
344+
return null;
345+
}
346+
return null;
347+
}
348+
}
336349

337350
private EntityRowMapper<?> getEntityRowMapper(Class<?> domainType) {
338351
return new EntityRowMapper<>(getRequiredPersistentEntity(domainType), context, converter, accessStrategy);

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/support/JdbcUtil.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
* Contains methods dealing with the quirks of JDBC, independent of any Entity, Aggregate or Repository abstraction.
3333
*
3434
* @author Jens Schauder
35+
* @author Thomas Lang
3536
*/
3637
@UtilityClass
3738
public class JdbcUtil {
@@ -42,7 +43,7 @@ public class JdbcUtil {
4243

4344
sqlTypeMappings.put(String.class, Types.VARCHAR);
4445
sqlTypeMappings.put(BigInteger.class, Types.BIGINT);
45-
sqlTypeMappings.put(BigDecimal.class, Types.NUMERIC);
46+
sqlTypeMappings.put(BigDecimal.class, Types.DECIMAL);
4647
sqlTypeMappings.put(Byte.class, Types.TINYINT);
4748
sqlTypeMappings.put(byte.class, Types.TINYINT);
4849
sqlTypeMappings.put(Short.class, Types.SMALLINT);

spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/AggregateTemplateIntegrationTests.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.springframework.data.relational.core.conversion.RelationalConverter;
3535
import org.springframework.data.relational.core.mapping.Column;
3636
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
37+
import org.springframework.test.annotation.IfProfileValue;
3738
import org.springframework.test.context.ContextConfiguration;
3839
import org.springframework.test.context.junit4.rules.SpringClassRule;
3940
import org.springframework.test.context.junit4.rules.SpringMethodRule;
@@ -46,6 +47,7 @@
4647
* Integration tests for {@link JdbcAggregateTemplate}.
4748
*
4849
* @author Jens Schauder
50+
* @author Thomas Lang
4951
*/
5052
@ContextConfiguration
5153
@Transactional
@@ -143,6 +145,7 @@ public void saveAndDeleteAllWithReferencedEntity() {
143145
}
144146

145147
@Test // DATAJDBC-112
148+
@IfProfileValue(name = "spring.profiles.active", values = {"mysql", "postgres", "mariadb", "default"}) // DATAJDBC-278
146149
public void updateReferencedEntityFromNull() {
147150

148151
legoSet.setManual(null);
@@ -201,6 +204,7 @@ public void replaceReferencedEntity() {
201204
}
202205

203206
@Test // DATAJDBC-112
207+
@IfProfileValue(name = "spring.profiles.active", values = {"mysql", "postgres", "mariadb", "default"}) // DATAJDBC-278
204208
public void changeReferencedEntity() {
205209

206210
template.save(legoSet);

spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryPropertyConversionIntegrationTests.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.springframework.data.jdbc.testing.TestConfiguration;
4444
import org.springframework.data.relational.core.mapping.event.BeforeSaveEvent;
4545
import org.springframework.data.repository.CrudRepository;
46+
import org.springframework.test.annotation.IfProfileValue;
4647
import org.springframework.test.context.ContextConfiguration;
4748
import org.springframework.test.context.junit4.rules.SpringClassRule;
4849
import org.springframework.test.context.junit4.rules.SpringMethodRule;
@@ -53,6 +54,7 @@
5354
* something the database driver can handle.
5455
*
5556
* @author Jens Schauder
57+
* @author Thomas Lang
5658
*/
5759
@ContextConfiguration
5860
@Transactional
@@ -88,6 +90,7 @@ ApplicationListener<?> applicationListener() {
8890
@Autowired DummyEntityRepository repository;
8991

9092
@Test // DATAJDBC-95
93+
@IfProfileValue(name = "spring.profiles.active", values = {"mysql", "postgres", "mariadb", "default"}) // DATAJDBC-278
9194
public void saveAndLoadAnEntity() {
9295

9396
EntityWithColumnsRequiringConversions entity = repository.save(createDummyEntity());
@@ -106,6 +109,7 @@ public void saveAndLoadAnEntity() {
106109
}
107110

108111
@Test // DATAJDBC-95
112+
@IfProfileValue(name = "spring.profiles.active", values = {"mysql", "postgres", "mariadb", "default"}) // DATAJDBC-278
109113
public void existsById() {
110114

111115
EntityWithColumnsRequiringConversions entity = repository.save(createDummyEntity());
@@ -114,6 +118,7 @@ public void existsById() {
114118
}
115119

116120
@Test // DATAJDBC-95
121+
@IfProfileValue(name = "spring.profiles.active", values = {"mysql", "postgres", "mariadb", "default"}) // DATAJDBC-278
117122
public void findAllById() {
118123

119124
EntityWithColumnsRequiringConversions entity = repository.save(createDummyEntity());
@@ -122,6 +127,7 @@ public void findAllById() {
122127
}
123128

124129
@Test // DATAJDBC-95
130+
@IfProfileValue(name = "spring.profiles.active", values = {"mysql", "postgres", "mariadb", "default"}) // DATAJDBC-278
125131
public void deleteAll() {
126132

127133
EntityWithColumnsRequiringConversions entity = repository.save(createDummyEntity());
@@ -132,6 +138,7 @@ public void deleteAll() {
132138
}
133139

134140
@Test // DATAJDBC-95
141+
@IfProfileValue(name = "spring.profiles.active", values = {"mysql", "postgres", "mariadb", "default"}) // DATAJDBC-278
135142
public void deleteById() {
136143

137144
EntityWithColumnsRequiringConversions entity = repository.save(createDummyEntity());

spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryWithCollectionsIntegrationTests.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.springframework.data.jdbc.testing.TestConfiguration;
3838
import org.springframework.data.repository.CrudRepository;
3939
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
40+
import org.springframework.test.annotation.IfProfileValue;
4041
import org.springframework.test.context.ContextConfiguration;
4142
import org.springframework.test.context.junit4.rules.SpringClassRule;
4243
import org.springframework.test.context.junit4.rules.SpringMethodRule;
@@ -46,6 +47,7 @@
4647
* Very simple use cases for creation and usage of JdbcRepositories.
4748
*
4849
* @author Jens Schauder
50+
* @author Thomas Lang
4951
*/
5052
@ContextConfiguration
5153
@Transactional
@@ -134,6 +136,7 @@ public void findAllLoadsCollection() {
134136
}
135137

136138
@Test // DATAJDBC-113
139+
@IfProfileValue(name = "spring.profiles.active", values = {"mysql", "postgres", "mariadb", "default"}) // DATAJDBC-278
137140
public void updateSet() {
138141

139142
Element element1 = createElement("one");

spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryWithListsIntegrationTests.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.springframework.data.jdbc.testing.TestConfiguration;
3838
import org.springframework.data.repository.CrudRepository;
3939
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
40+
import org.springframework.test.annotation.IfProfileValue;
4041
import org.springframework.test.context.ContextConfiguration;
4142
import org.springframework.test.context.junit4.rules.SpringClassRule;
4243
import org.springframework.test.context.junit4.rules.SpringMethodRule;
@@ -46,6 +47,7 @@
4647
* Very simple use cases for creation and usage of JdbcRepositories for Entities that contain {@link List}s.
4748
*
4849
* @author Jens Schauder
50+
* @author Thomas Lang
4951
*/
5052
@ContextConfiguration
5153
@Transactional
@@ -134,6 +136,7 @@ public void findAllLoadsList() {
134136
}
135137

136138
@Test // DATAJDBC-130
139+
@IfProfileValue(name = "spring.profiles.active", values = {"mysql", "postgres", "mariadb", "default"}) // DATAJDBC-278
137140
public void updateList() {
138141

139142
Element element1 = createElement("one");

spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryWithMapsIntegrationTests.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.springframework.data.jdbc.testing.TestConfiguration;
3737
import org.springframework.data.repository.CrudRepository;
3838
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
39+
import org.springframework.test.annotation.IfProfileValue;
3940
import org.springframework.test.context.ContextConfiguration;
4041
import org.springframework.test.context.junit4.rules.SpringClassRule;
4142
import org.springframework.test.context.junit4.rules.SpringMethodRule;
@@ -45,6 +46,7 @@
4546
* Very simple use cases for creation and usage of JdbcRepositories for Entities that contain {@link java.util.Map}s.
4647
*
4748
* @author Jens Schauder
49+
* @author Thomas Lang
4850
*/
4951
@ContextConfiguration
5052
@Transactional
@@ -133,6 +135,7 @@ public void findAllLoadsMap() {
133135
}
134136

135137
@Test // DATAJDBC-131
138+
@IfProfileValue(name = "spring.profiles.active", values = {"mysql", "postgres", "mariadb", "default"}) // DATAJDBC-278
136139
public void updateMap() {
137140

138141
Element element1 = createElement("one");
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2017-2018 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+
* http://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.data.jdbc.testing;
17+
18+
import com.microsoft.sqlserver.jdbc.SQLServerDataSource;
19+
import org.springframework.context.annotation.Configuration;
20+
import org.springframework.context.annotation.Profile;
21+
import org.testcontainers.containers.MSSQLServerContainer;
22+
23+
import javax.sql.DataSource;
24+
25+
26+
/**
27+
* {@link DataSource} setup for PostgreSQL.
28+
* <p>
29+
* Configuration for a MSSQL Datasource.
30+
*
31+
* @author Thomas Lang
32+
* @see <a href="https://github.com/testcontainers/testcontainers-java/tree/master/modules/mssqlserver"></a>
33+
*/
34+
@Configuration
35+
@Profile({"mssql"})
36+
public class MsSqlDataSourceConfiguration extends DataSourceConfiguration {
37+
38+
private static final MSSQLServerContainer mssqlserver = new MSSQLServerContainer();
39+
40+
static {
41+
mssqlserver.start();
42+
}
43+
44+
/*
45+
* (non-Javadoc)
46+
* @see org.springframework.data.jdbc.testing.DataSourceConfiguration#createDataSource()
47+
*/
48+
@Override
49+
protected DataSource createDataSource() {
50+
SQLServerDataSource sqlServerDataSource = new SQLServerDataSource();
51+
sqlServerDataSource.setURL(mssqlserver.getJdbcUrl());
52+
sqlServerDataSource.setUser(mssqlserver.getUsername());
53+
sqlServerDataSource.setPassword(mssqlserver.getPassword());
54+
return sqlServerDataSource;
55+
}
56+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
microsoft/mssql-server-linux:2017-CU6

0 commit comments

Comments
 (0)