diff --git a/pom.xml b/pom.xml
index 6050cb016e..04a90d5855 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-relational-parent
- 3.4.0-SNAPSHOT
+ 3.4.0-1737-nullable-embedded-with-collection-SNAPSHOT
pom
Spring Data Relational Parent
diff --git a/spring-data-jdbc-distribution/pom.xml b/spring-data-jdbc-distribution/pom.xml
index 4626db4364..583df255fa 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
- 3.4.0-SNAPSHOT
+ 3.4.0-1737-nullable-embedded-with-collection-SNAPSHOT
../pom.xml
diff --git a/spring-data-jdbc/pom.xml b/spring-data-jdbc/pom.xml
index aa44f71832..dc1217579b 100644
--- a/spring-data-jdbc/pom.xml
+++ b/spring-data-jdbc/pom.xml
@@ -6,7 +6,7 @@
4.0.0
spring-data-jdbc
- 3.4.0-SNAPSHOT
+ 3.4.0-1737-nullable-embedded-with-collection-SNAPSHOT
Spring Data JDBC
Spring Data module for JDBC repositories.
@@ -15,7 +15,7 @@
org.springframework.data
spring-data-relational-parent
- 3.4.0-SNAPSHOT
+ 3.4.0-1737-nullable-embedded-with-collection-SNAPSHOT
diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/MappingJdbcConverter.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/MappingJdbcConverter.java
index ebb4d58717..97db411446 100644
--- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/MappingJdbcConverter.java
+++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/MappingJdbcConverter.java
@@ -421,7 +421,7 @@ public T getPropertyValue(RelationalPersistentProperty property) {
@Override
public boolean hasValue(RelationalPersistentProperty property) {
- if (property.isCollectionLike() || property.isMap()) {
+ if ((property.isCollectionLike() && property.isEntity())|| property.isMap()) {
// attempt relation fetch
return true;
}
diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/AbstractJdbcAggregateTemplateIntegrationTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/AbstractJdbcAggregateTemplateIntegrationTests.java
index c7ac9275ab..a4ad36e04f 100644
--- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/AbstractJdbcAggregateTemplateIntegrationTests.java
+++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/AbstractJdbcAggregateTemplateIntegrationTests.java
@@ -22,16 +22,8 @@
import static org.springframework.data.jdbc.testing.TestDatabaseFeatures.Feature.*;
import java.time.LocalDateTime;
+import java.util.*;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
import java.util.function.Function;
import java.util.stream.IntStream;
@@ -61,6 +53,7 @@
import org.springframework.data.mapping.context.InvalidPersistentPropertyPath;
import org.springframework.data.relational.core.conversion.DbActionExecutionException;
import org.springframework.data.relational.core.mapping.Column;
+import org.springframework.data.relational.core.mapping.Embedded;
import org.springframework.data.relational.core.mapping.InsertOnlyProperty;
import org.springframework.data.relational.core.mapping.MappedCollection;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
@@ -778,6 +771,36 @@ void saveAndLoadAnEntityWithSet() {
assertThat(reloaded.digits).isEqualTo(new HashSet<>(asList("one", "two", "three")));
}
+ @Test //GH-1737
+ @EnabledOnFeature(SUPPORTS_ARRAYS)
+ void saveAndLoadEmbeddedArray() {
+
+ EmbeddedStringListOwner embeddedStringListOwner = new EmbeddedStringListOwner();
+ embeddedStringListOwner.embeddedStringList = new EmbeddedStringList();
+ embeddedStringListOwner.embeddedStringList.digits = List.of("one", "two", "three");
+
+ EmbeddedStringListOwner saved = template.save(embeddedStringListOwner);
+
+ EmbeddedStringListOwner reloaded = template.findById(saved.id, EmbeddedStringListOwner.class);
+
+ assertThat(reloaded.embeddedStringList.digits).containsExactly("one", "two", "three");
+ }
+
+ @Test //GH-1737
+ @EnabledOnFeature(SUPPORTS_ARRAYS)
+ void saveAndLoadEmptyEmbeddedArray() {
+
+ EmbeddedStringListOwner embeddedStringListOwner = new EmbeddedStringListOwner();
+ embeddedStringListOwner.embeddedStringList = new EmbeddedStringList();
+ embeddedStringListOwner.embeddedStringList.digits = emptyList();
+
+ EmbeddedStringListOwner saved = template.save(embeddedStringListOwner);
+
+ EmbeddedStringListOwner reloaded = template.findById(saved.id, EmbeddedStringListOwner.class);
+
+ assertThat(reloaded.embeddedStringList).isNull();
+ }
+
@Test
// DATAJDBC-327
void saveAndLoadAnEntityWithByteArray() {
@@ -919,7 +942,7 @@ void readOnlyGetsLoadedButNotWritten() {
assertThat(
jdbcTemplate.queryForObject("SELECT read_only FROM with_read_only", Collections.emptyMap(), String.class))
- .isEqualTo("from-db");
+ .isEqualTo("from-db");
}
@Test
@@ -1258,7 +1281,8 @@ void recordOfSet() {
@Test // GH-1656
void mapWithEnumKey() {
- EnumMapOwner enumMapOwner = template.save(new EnumMapOwner(null, "OwnerName", Map.of(Color.BLUE, new MapElement("Element"))));
+ EnumMapOwner enumMapOwner = template
+ .save(new EnumMapOwner(null, "OwnerName", Map.of(Color.BLUE, new MapElement("Element"))));
Iterable enumMapOwners = template.findAll(EnumMapOwner.class);
@@ -1266,7 +1290,7 @@ void mapWithEnumKey() {
}
@Test // GH-1684
- void oneToOneWithIdenticalIdColumnName(){
+ void oneToOneWithIdenticalIdColumnName() {
WithOneToOne saved = template.insert(new WithOneToOne("one", new Referenced(23L)));
@@ -1369,6 +1393,17 @@ private static class FloatListOwner {
List digits = new ArrayList<>();
}
+ @Table("ARRAY_OWNER")
+ private static class EmbeddedStringListOwner {
+ @Id Long id;
+
+ @Embedded(onEmpty = Embedded.OnEmpty.USE_NULL, prefix = "") EmbeddedStringList embeddedStringList;
+ }
+
+ private static class EmbeddedStringList {
+ List digits = new ArrayList<>();
+ }
+
static class LegoSet {
@Column("id1")
@@ -2096,7 +2131,8 @@ record Book(String name) {
record EnumMapOwner(@Id Long id, String name, Map map) {
}
- record WithOneToOne(@Id String id,@MappedCollection(idColumn = "renamed") Referenced referenced){}
+ record WithOneToOne(@Id String id, @MappedCollection(idColumn = "renamed") Referenced referenced) {
+ }
record Referenced(@Id Long id) {
}
diff --git a/spring-data-r2dbc/pom.xml b/spring-data-r2dbc/pom.xml
index 3168f9d4f6..979b7a28a1 100644
--- a/spring-data-r2dbc/pom.xml
+++ b/spring-data-r2dbc/pom.xml
@@ -6,7 +6,7 @@
4.0.0
spring-data-r2dbc
- 3.4.0-SNAPSHOT
+ 3.4.0-1737-nullable-embedded-with-collection-SNAPSHOT
Spring Data R2DBC
Spring Data module for R2DBC
@@ -15,7 +15,7 @@
org.springframework.data
spring-data-relational-parent
- 3.4.0-SNAPSHOT
+ 3.4.0-1737-nullable-embedded-with-collection-SNAPSHOT
diff --git a/spring-data-relational/pom.xml b/spring-data-relational/pom.xml
index 3ba39b861c..f10edf138a 100644
--- a/spring-data-relational/pom.xml
+++ b/spring-data-relational/pom.xml
@@ -6,7 +6,7 @@
4.0.0
spring-data-relational
- 3.4.0-SNAPSHOT
+ 3.4.0-1737-nullable-embedded-with-collection-SNAPSHOT
Spring Data Relational
Spring Data Relational support
@@ -14,7 +14,7 @@
org.springframework.data
spring-data-relational-parent
- 3.4.0-SNAPSHOT
+ 3.4.0-1737-nullable-embedded-with-collection-SNAPSHOT
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/MappingRelationalConverter.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/MappingRelationalConverter.java
index 3469c8b9fd..3233d1a270 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/MappingRelationalConverter.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/MappingRelationalConverter.java
@@ -44,16 +44,7 @@
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.PersistentPropertyPathAccessor;
import org.springframework.data.mapping.context.MappingContext;
-import org.springframework.data.mapping.model.CachingValueExpressionEvaluatorFactory;
-import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
-import org.springframework.data.mapping.model.EntityInstantiator;
-import org.springframework.data.mapping.model.ParameterValueProvider;
-import org.springframework.data.mapping.model.PersistentEntityParameterValueProvider;
-import org.springframework.data.mapping.model.PropertyValueProvider;
-import org.springframework.data.mapping.model.SimpleTypeHolder;
-import org.springframework.data.mapping.model.SpELContext;
-import org.springframework.data.mapping.model.ValueExpressionEvaluator;
-import org.springframework.data.mapping.model.ValueExpressionParameterValueProvider;
+import org.springframework.data.mapping.model.*;
import org.springframework.data.projection.EntityProjection;
import org.springframework.data.projection.EntityProjectionIntrospector;
import org.springframework.data.projection.EntityProjectionIntrospector.ProjectionPredicate;
@@ -1168,7 +1159,43 @@ public Object getValue(AggregatePath path) {
@Override
public boolean hasValue(AggregatePath path) {
- return document.get(path.getColumnInfo().alias().getReference()) != null;
+ Object value = document.get(path.getColumnInfo().alias().getReference());
+
+ if (value == null) {
+ return false;
+ }
+ if (!path.isCollectionLike()) {
+ return true;
+ }
+
+ if (value instanceof char[] ar) {
+ return ar.length != 0;
+ }
+ if (value instanceof byte[] ar) {
+ return ar.length != 0;
+ }
+ if (value instanceof short[] ar) {
+ return ar.length != 0;
+ }
+ if (value instanceof int[] ar) {
+ return ar.length != 0;
+ }
+ if (value instanceof long[] ar) {
+ return ar.length != 0;
+ }
+ if (value instanceof float[] ar) {
+ return ar.length != 0;
+ }
+ if (value instanceof double[] ar) {
+ return ar.length != 0;
+ }
+ if (value instanceof Object[] ar) {
+ return ar.length != 0;
+ }
+ if (value instanceof Collection> col) {
+ return !col.isEmpty();
+ }
+ return true;
}
@Override