diff --git a/pom.xml b/pom.xml index d2cdc888fa..70d15890db 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-relational-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.DATAJDBC-538-SNAPSHOT pom Spring Data Relational Parent diff --git a/spring-data-jdbc-distribution/pom.xml b/spring-data-jdbc-distribution/pom.xml index 858a5f4b4b..98c6973bdb 100644 --- a/spring-data-jdbc-distribution/pom.xml +++ b/spring-data-jdbc-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-relational-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.DATAJDBC-538-SNAPSHOT ../pom.xml diff --git a/spring-data-jdbc/pom.xml b/spring-data-jdbc/pom.xml index c172e3e683..c8f99e740b 100644 --- a/spring-data-jdbc/pom.xml +++ b/spring-data-jdbc/pom.xml @@ -6,7 +6,7 @@ 4.0.0 spring-data-jdbc - 2.0.0.BUILD-SNAPSHOT + 2.0.0.DATAJDBC-538-SNAPSHOT Spring Data JDBC Spring Data module for JDBC repositories. @@ -15,7 +15,7 @@ org.springframework.data spring-data-relational-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.DATAJDBC-538-SNAPSHOT diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultDataAccessStrategy.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultDataAccessStrategy.java index 80b7623db1..afa4b5002a 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultDataAccessStrategy.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultDataAccessStrategy.java @@ -18,9 +18,7 @@ import static org.springframework.data.jdbc.core.convert.SqlGenerator.*; import java.sql.JDBCType; -import java.sql.PreparedStatement; import java.sql.ResultSet; -import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -28,7 +26,6 @@ import java.util.Map; import java.util.function.Predicate; -import org.springframework.dao.DataAccessException; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.dao.InvalidDataAccessApiUsageException; @@ -40,6 +37,7 @@ import org.springframework.data.mapping.PersistentPropertyAccessor; import org.springframework.data.mapping.PersistentPropertyPath; import org.springframework.data.mapping.PropertyHandler; +import org.springframework.data.relational.core.dialect.LockClause; import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension; import org.springframework.data.relational.core.mapping.RelationalMappingContext; import org.springframework.data.relational.core.mapping.RelationalPersistentEntity; @@ -47,8 +45,6 @@ import org.springframework.data.relational.core.sql.IdentifierProcessing; import org.springframework.data.relational.core.sql.LockMode; import org.springframework.data.relational.core.sql.SqlIdentifier; -import org.springframework.jdbc.core.PreparedStatementCallback; -import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; import org.springframework.jdbc.core.namedparam.SqlParameterSource; @@ -254,7 +250,8 @@ public void acquireLockById(Object id, LockMode lockMode, Class domainTyp String acquireLockByIdSql = sql(domainType).getAcquireLockById(lockMode); SqlIdentifierParameterSource parameter = createIdParameterSource(id, domainType); - operations.execute(acquireLockByIdSql, parameter, ps -> {ps.execute(); return null;}); + + operations.query(acquireLockByIdSql, parameter, ResultSet::next); } /* @@ -265,7 +262,7 @@ public void acquireLockById(Object id, LockMode lockMode, Class domainTyp public void acquireLockAll(LockMode lockMode, Class domainType) { String acquireLockAllSql = sql(domainType).getAcquireLockAll(lockMode); - operations.getJdbcOperations().execute(acquireLockAllSql); + operations.getJdbcOperations().query(acquireLockAllSql, ResultSet::next); } /* diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryConcurrencyIntegrationTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryConcurrencyIntegrationTests.java index ac56aabd53..2a46c02d5d 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryConcurrencyIntegrationTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryConcurrencyIntegrationTests.java @@ -25,14 +25,18 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.StringJoiner; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; import java.util.function.UnaryOperator; +import org.assertj.core.api.Assertions; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; +import org.junit.platform.commons.util.ExceptionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -86,6 +90,35 @@ DummyEntityRepository dummyEntityRepository() { TransactionTemplate transactionTemplate; List exceptions; + @BeforeClass + public static void beforeClass() { + + Assertions.registerFormatterForType(CopyOnWriteArrayList.class, l -> { + + StringJoiner joiner = new StringJoiner(", ", "List(", ")"); + l.forEach(e -> { + + if (e instanceof Throwable) { + printThrowable(joiner,(Throwable) e); + } else { + joiner.add(e.toString()); + } + }); + + return joiner.toString(); + }); + } + + private static void printThrowable(StringJoiner joiner, Throwable t) { + + joiner.add(t.toString() + ExceptionUtils.readStackTrace(t)); + if (t.getCause() != null) { + + joiner.add("\ncaused by:\n"); + printThrowable(joiner, t.getCause()); + } + } + @Before public void before() { diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/Db2DataSourceConfiguration.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/Db2DataSourceConfiguration.java index 044f691622..fd06126c21 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/Db2DataSourceConfiguration.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/Db2DataSourceConfiguration.java @@ -55,7 +55,7 @@ protected DataSource createDataSource() { if (DB_2_CONTAINER == null) { LOG.info("DB2 starting..."); - Db2Container container = new Db2Container(); + Db2Container container = new Db2Container().withReuse(true); container.start(); LOG.info("DB2 started"); diff --git a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-db2.sql b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-db2.sql index fde21b0de5..0332be5eca 100644 --- a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-db2.sql +++ b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-db2.sql @@ -1,3 +1,41 @@ +DROP TABLE MANUAL; +DROP TABLE LEGO_SET; + +DROP TABLE Child_No_Id; +DROP TABLE ONE_TO_ONE_PARENT; + +DROP TABLE ELEMENT_NO_ID; +DROP TABLE LIST_PARENT; + +DROP TABLE BYTE_ARRAY_OWNER; + +DROP TABLE CHAIN0; +DROP TABLE CHAIN1; +DROP TABLE CHAIN2; +DROP TABLE CHAIN3; +DROP TABLE CHAIN4; + +DROP TABLE NO_ID_CHAIN0; +DROP TABLE NO_ID_CHAIN1; +DROP TABLE NO_ID_CHAIN2; +DROP TABLE NO_ID_CHAIN3; +DROP TABLE NO_ID_CHAIN4; + +DROP TABLE NO_ID_MAP_CHAIN0; +DROP TABLE NO_ID_MAP_CHAIN1; +DROP TABLE NO_ID_MAP_CHAIN2; +DROP TABLE NO_ID_MAP_CHAIN3; +DROP TABLE NO_ID_MAP_CHAIN4; + +DROP TABLE NO_ID_LIST_CHAIN0; +DROP TABLE NO_ID_LIST_CHAIN1; +DROP TABLE NO_ID_LIST_CHAIN2; +DROP TABLE NO_ID_LIST_CHAIN3; +DROP TABLE NO_ID_LIST_CHAIN4; + +DROP TABLE WITH_READ_ONLY; +DROP TABLE VERSIONED_AGGREGATE; + CREATE TABLE LEGO_SET ( "id1" BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, diff --git a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.repository/JdbcRepositoryConcurrencyIntegrationTests-db2.sql b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.repository/JdbcRepositoryConcurrencyIntegrationTests-db2.sql new file mode 100644 index 0000000000..aef62bb57a --- /dev/null +++ b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.repository/JdbcRepositoryConcurrencyIntegrationTests-db2.sql @@ -0,0 +1,5 @@ +DROP TABLE element; +DROP TABLE dummy_entity; + +CREATE TABLE dummy_entity ( id BIGINT GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ) NOT NULL PRIMARY KEY, NAME VARCHAR(100)); +CREATE TABLE element (id BIGINT GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ) NOT NULL PRIMARY KEY, content BIGINT, Dummy_Entity_key BIGINT,dummy_entity BIGINT); diff --git a/spring-data-relational/pom.xml b/spring-data-relational/pom.xml index 0a529399c3..1ab02dbf25 100644 --- a/spring-data-relational/pom.xml +++ b/spring-data-relational/pom.xml @@ -6,7 +6,7 @@ 4.0.0 spring-data-relational - 2.0.0.BUILD-SNAPSHOT + 2.0.0.DATAJDBC-538-SNAPSHOT Spring Data Relational Spring Data Relational support @@ -14,7 +14,7 @@ org.springframework.data spring-data-relational-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.DATAJDBC-538-SNAPSHOT diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/Db2Dialect.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/Db2Dialect.java index a646885f89..1259d3a4b7 100644 --- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/Db2Dialect.java +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/Db2Dialect.java @@ -41,7 +41,7 @@ protected Db2Dialect() {} */ @Override public String getLimit(long limit) { - return "FIRST " + limit + " ROWS ONLY"; + return "FETCH FIRST " + limit + " ROWS ONLY"; } /* @@ -83,7 +83,18 @@ public LimitClause limit() { @Override public LockClause lock() { - return AnsiDialect.LOCK_CLAUSE; + + return new LockClause() { + @Override + public String getLock(LockOptions lockOptions) { + return "FOR UPDATE WITH RS USE AND KEEP EXCLUSIVE LOCKS"; + } + + @Override + public Position getClausePosition() { + return Position.AFTER_ORDER_BY; + } + }; } /*