From 99b1fbdb7346b6917ba984e2599be0618d912453 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Tue, 15 Oct 2019 09:36:16 +0200 Subject: [PATCH 1/4] DATAJDBC-431 - Prepare branch --- pom.xml | 2 +- spring-data-jdbc-distribution/pom.xml | 2 +- spring-data-jdbc/pom.xml | 4 ++-- spring-data-relational/pom.xml | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 87b7e95ebe..01aba6d43c 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-relational-parent - 1.2.0.BUILD-SNAPSHOT + 1.2.0.DATAJDBC-431-SNAPSHOT pom Spring Data Relational Parent diff --git a/spring-data-jdbc-distribution/pom.xml b/spring-data-jdbc-distribution/pom.xml index f2bbb72319..9afa9305bd 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 - 1.2.0.BUILD-SNAPSHOT + 1.2.0.DATAJDBC-431-SNAPSHOT ../pom.xml diff --git a/spring-data-jdbc/pom.xml b/spring-data-jdbc/pom.xml index 0904eb8136..de14dce478 100644 --- a/spring-data-jdbc/pom.xml +++ b/spring-data-jdbc/pom.xml @@ -5,7 +5,7 @@ 4.0.0 spring-data-jdbc - 1.2.0.BUILD-SNAPSHOT + 1.2.0.DATAJDBC-431-SNAPSHOT Spring Data JDBC Spring Data module for JDBC repositories. @@ -14,7 +14,7 @@ org.springframework.data spring-data-relational-parent - 1.2.0.BUILD-SNAPSHOT + 1.2.0.DATAJDBC-431-SNAPSHOT diff --git a/spring-data-relational/pom.xml b/spring-data-relational/pom.xml index 1751c4244e..24956f2581 100644 --- a/spring-data-relational/pom.xml +++ b/spring-data-relational/pom.xml @@ -5,7 +5,7 @@ 4.0.0 spring-data-relational - 1.2.0.BUILD-SNAPSHOT + 1.2.0.DATAJDBC-431-SNAPSHOT Spring Data Relational Spring Data Relational support @@ -13,7 +13,7 @@ org.springframework.data spring-data-relational-parent - 1.2.0.BUILD-SNAPSHOT + 1.2.0.DATAJDBC-431-SNAPSHOT From 83487cfda7a9cc6dad31c9480d4eefc6546120f2 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Mon, 14 Oct 2019 16:09:35 +0200 Subject: [PATCH 2/4] DATAJDBC-431 - ReadOnlyProperty now gets properly handled. The problem was that the SqlGenerator honored the annotation but they were included as query parameters and therefore automatically added back again. Also: * Simplified the relevant filter in the SqlGenerator. * Introduced a meta annotation for running tests only agains HsqlDb. --- .../convert/DefaultDataAccessStrategy.java | 2 +- .../data/jdbc/core/convert/SqlGenerator.java | 3 +- ...JdbcAggregateTemplateIntegrationTests.java | 25 ++++++++++++ .../data/jdbc/testing/HsqlDbOnly.java | 40 +++++++++++++++++++ ...AggregateTemplateIntegrationTests-hsql.sql | 8 +++- 5 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/HsqlDbOnly.java 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 3f54d1d3f0..476f1a1b41 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 @@ -323,7 +323,7 @@ private MapSqlParameterSource getParameterSource(S instance, RelationalPe persistentEntity.doWithProperties((PropertyHandler) property -> { - if (skipProperty.test(property)) { + if (skipProperty.test(property) || !property.isWritable()) { return; } if (property.isEntity() && !property.isEmbedded()) { diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlGenerator.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlGenerator.java index c24d32ad8c..f7a93fca35 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlGenerator.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlGenerator.java @@ -29,7 +29,6 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; -import org.springframework.data.annotation.ReadOnlyProperty; import org.springframework.data.jdbc.repository.support.SimpleJdbcRepository; import org.springframework.data.mapping.PersistentPropertyPath; import org.springframework.data.mapping.PropertyHandler; @@ -623,7 +622,7 @@ private void initSimpleColumnName(RelationalPersistentProperty property, String idColumnNames.add(columnName); } - if (!property.isWritable() || property.isAnnotationPresent(ReadOnlyProperty.class)) { + if (!property.isWritable()) { readOnlyColumnNames.add(columnName); } } diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateIntegrationTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateIntegrationTests.java index c388b46234..ac91b39c5e 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateIntegrationTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateIntegrationTests.java @@ -21,8 +21,10 @@ import lombok.Data; import lombok.EqualsAndHashCode; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -41,8 +43,10 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.ReadOnlyProperty; import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.jdbc.testing.DatabaseProfileValueSource; +import org.springframework.data.jdbc.testing.HsqlDbOnly; import org.springframework.data.jdbc.testing.TestConfiguration; import org.springframework.data.relational.core.conversion.RelationalConverter; import org.springframework.data.relational.core.mapping.Column; @@ -597,6 +601,20 @@ public void shouldDeleteChainOfMapsWithoutIds() { }); } + @Test // DATAJDBC-431 + @HsqlDbOnly + public void readOnlyGetsLoadedButNotWritten() { + + WithReadOnly entity = new WithReadOnly(); + entity.name = "Alfred"; + entity.readOnly = "not used"; + + template.save(entity); + + assertThat( + jdbcTemplate.queryForObject("SELECT read_only FROM with_read_only", Collections.emptyMap(), String.class)).isEqualTo("from-db"); + } + private static NoIdMapChain4 createNoIdMapTree() { NoIdMapChain4 chain4 = new NoIdMapChain4(); @@ -855,6 +873,13 @@ static class NoIdMapChain4 { Map chain3 = new HashMap<>(); } + static class WithReadOnly { + @Id Long id; + String name; + @ReadOnlyProperty + String readOnly; + } + @Configuration @Import(TestConfiguration.class) static class Config { diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/HsqlDbOnly.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/HsqlDbOnly.java new file mode 100644 index 0000000000..d4ac0eed77 --- /dev/null +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/HsqlDbOnly.java @@ -0,0 +1,40 @@ +/* + * Copyright 2019 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.data.jdbc.testing; + +import org.springframework.test.annotation.IfProfileValue; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Run the annotated test only against a HsqlDb database. + * + * Requires the use of + * + * @author Jens Schauder + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@IfProfileValue(name = "current.database.is.not.hsqldb", value = "false") +public @interface HsqlDbOnly { +} diff --git a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-hsql.sql b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-hsql.sql index bd14282b3e..02071e25c8 100644 --- a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-hsql.sql +++ b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-hsql.sql @@ -292,4 +292,10 @@ CREATE TABLE NO_ID_MAP_CHAIN0 NO_ID_MAP_CHAIN3_KEY, NO_ID_MAP_CHAIN2_KEY ) -); \ No newline at end of file +); + +CREATE TABLE WITH_READ_ONLY ( + ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 40) PRIMARY KEY, + NAME VARCHAR(200), + READ_ONLY VARCHAR(200) DEFAULT 'from-db' +) \ No newline at end of file From f9700bf8e152010a4e0c4ddf0981e5cd9a1efaf9 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Tue, 15 Oct 2019 14:02:44 +0200 Subject: [PATCH 3/4] DATAJDBC-431 - Polishing. Improved and corrected nullability annotations. --- .../data/jdbc/core/convert/DataAccessStrategy.java | 1 + .../data/jdbc/core/convert/DefaultDataAccessStrategy.java | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DataAccessStrategy.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DataAccessStrategy.java index a1319ddb5b..ec004609f5 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DataAccessStrategy.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DataAccessStrategy.java @@ -58,6 +58,7 @@ public interface DataAccessStrategy extends RelationResolver { * @return the id generated by the database if any. * @since 1.1 */ + @Nullable default Object insert(T instance, Class domainType, Identifier identifier) { return insert(instance, domainType, identifier.toMap()); } 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 476f1a1b41..ecef50c8f8 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 @@ -313,7 +313,7 @@ public boolean existsById(Object id, Class domainType) { return result; } - private MapSqlParameterSource getParameterSource(S instance, RelationalPersistentEntity persistentEntity, + private MapSqlParameterSource getParameterSource(@Nullable S instance, RelationalPersistentEntity persistentEntity, String prefix, Predicate skipProperty) { MapSqlParameterSource parameters = new MapSqlParameterSource(); @@ -418,7 +418,7 @@ private MapSqlParameterSource createIdParameterSource(Object id, Class do } private void addConvertedPropertyValue(MapSqlParameterSource parameterSource, RelationalPersistentProperty property, - Object value, String paramName) { + @Nullable Object value, String paramName) { JdbcValue jdbcValue = converter.writeJdbcValue( // value, // From 8926d08ced211644617db71cdd41351db8002a84 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Fri, 25 Oct 2019 07:47:14 +0200 Subject: [PATCH 4/4] DATAJDBC-431 - Polishing. Fixed broken Javadoc. --- .../java/org/springframework/data/jdbc/testing/HsqlDbOnly.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/HsqlDbOnly.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/HsqlDbOnly.java index d4ac0eed77..4990b6d148 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/HsqlDbOnly.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/HsqlDbOnly.java @@ -27,7 +27,7 @@ /** * Run the annotated test only against a HsqlDb database. * - * Requires the use of + * Requires the use of {@code @ProfileValueSourceConfiguration(DatabaseProfileValueSource.class)} on the test. * * @author Jens Schauder */