Browse Source

Fix regression of loading empty arrays.

Closes #1826
See #1812
pull/1830/head
Jens Schauder 2 years ago
parent
commit
7bd907c5e6
No known key found for this signature in database
GPG Key ID: 74F6C554AE971567
  1. 29
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/MappingJdbcConverter.java
  2. 37
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/AbstractJdbcAggregateTemplateIntegrationTests.java
  3. 35
      spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/MappingRelationalConverter.java

29
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/MappingJdbcConverter.java

@ -26,7 +26,6 @@ import java.util.function.Function;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
import org.springframework.core.convert.ConverterNotFoundException; import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.converter.Converter;
@ -422,7 +421,7 @@ public class MappingJdbcConverter extends MappingRelationalConverter implements
@Override @Override
public boolean hasValue(RelationalPersistentProperty property) { public boolean hasValue(RelationalPersistentProperty property) {
if ((property.isCollectionLike() && property.isEntity())|| property.isMap()) { if ((property.isCollectionLike() && property.isEntity()) || property.isMap()) {
// attempt relation fetch // attempt relation fetch
return true; return true;
} }
@ -445,6 +444,32 @@ public class MappingJdbcConverter extends MappingRelationalConverter implements
return delegate.hasValue(aggregatePath); return delegate.hasValue(aggregatePath);
} }
@Override
public boolean hasNonEmptyValue(RelationalPersistentProperty property) {
if ((property.isCollectionLike() && property.isEntity()) || property.isMap()) {
// attempt relation fetch
return true;
}
AggregatePath aggregatePath = context.aggregatePath();
if (property.isEntity()) {
RelationalPersistentEntity<?> entity = getMappingContext().getRequiredPersistentEntity(property);
if (entity.hasIdProperty()) {
RelationalPersistentProperty referenceId = entity.getRequiredIdProperty();
AggregatePath toUse = aggregatePath.append(referenceId);
return delegate.hasValue(toUse);
}
return delegate.hasValue(aggregatePath.getTableInfo().reverseColumnInfo().alias());
}
return delegate.hasNonEmptyValue(aggregatePath);
}
@Override @Override
public RelationalPropertyValueProvider withContext(ConversionContext context) { public RelationalPropertyValueProvider withContext(ConversionContext context) {

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

@ -681,6 +681,26 @@ abstract class AbstractJdbcAggregateTemplateIntegrationTests {
assertThat(reloaded.digits).isEqualTo(new String[] { "one", "two", "three" }); assertThat(reloaded.digits).isEqualTo(new String[] { "one", "two", "three" });
} }
@Test // GH-1826
@EnabledOnFeature(SUPPORTS_ARRAYS)
void saveAndLoadAnEntityWithEmptyArray() {
ArrayOwner arrayOwner = new ArrayOwner();
arrayOwner.digits = new String[] { };
ArrayOwner saved = template.save(arrayOwner);
assertThat(saved.id).isNotNull();
ArrayOwner reloaded = template.findById(saved.id, ArrayOwner.class);
assertThat(reloaded).isNotNull();
assertThat(reloaded.id).isEqualTo(saved.id);
assertThat(reloaded.digits) //
.isNotNull() //
.isEmpty();
}
@Test // DATAJDBC-259, DATAJDBC-512 @Test // DATAJDBC-259, DATAJDBC-512
@EnabledOnFeature(SUPPORTS_MULTIDIMENSIONAL_ARRAYS) @EnabledOnFeature(SUPPORTS_MULTIDIMENSIONAL_ARRAYS)
void saveAndLoadAnEntityWithMultidimensionalArray() { void saveAndLoadAnEntityWithMultidimensionalArray() {
@ -718,6 +738,23 @@ abstract class AbstractJdbcAggregateTemplateIntegrationTests {
assertThat(reloaded.digits).isEqualTo(asList("one", "two", "three")); assertThat(reloaded.digits).isEqualTo(asList("one", "two", "three"));
} }
@Test // DATAJDBC-1826
@EnabledOnFeature(SUPPORTS_ARRAYS)
void saveAndLoadAnEntityWithEmptyList() {
ListOwner arrayOwner = new ListOwner();
ListOwner saved = template.save(arrayOwner);
assertThat(saved.id).isNotNull();
ListOwner reloaded = template.findById(saved.id, ListOwner.class);
assertThat(reloaded).isNotNull();
assertThat(reloaded.id).isEqualTo(saved.id);
assertThat(reloaded.digits).isNotNull().isEmpty();
}
@Test // GH-1033 @Test // GH-1033
@EnabledOnFeature(SUPPORTS_ARRAYS) @EnabledOnFeature(SUPPORTS_ARRAYS)
void saveAndLoadAnEntityWithListOfDouble() { void saveAndLoadAnEntityWithListOfDouble() {

35
spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/MappingRelationalConverter.java

@ -490,6 +490,11 @@ public class MappingRelationalConverter extends AbstractRelationalConverter
return withContext(context.forProperty(property)).hasValue(property); return withContext(context.forProperty(property)).hasValue(property);
} }
@Override
public boolean hasNonEmptyValue(RelationalPersistentProperty property) {
return withContext(context.forProperty(property)).hasNonEmptyValue(property);
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Nullable @Nullable
@Override @Override
@ -565,6 +570,7 @@ public class MappingRelationalConverter extends AbstractRelationalConverter
continue; continue;
} }
// this hasValue should actually check against null
if (!valueProviderToUse.hasValue(property)) { if (!valueProviderToUse.hasValue(property)) {
continue; continue;
} }
@ -608,7 +614,7 @@ public class MappingRelationalConverter extends AbstractRelationalConverter
return true; return true;
} }
} else if (contextual.hasValue(persistentProperty)) { } else if (contextual.hasNonEmptyValue(persistentProperty)) {
return true; return true;
} }
} }
@ -1051,6 +1057,13 @@ public class MappingRelationalConverter extends AbstractRelationalConverter
*/ */
boolean hasValue(RelationalPersistentProperty property); boolean hasValue(RelationalPersistentProperty property);
/**
* Determine whether there is a non empty value for the given {@link RelationalPersistentProperty}.
*
* @param property the property to check for whether a value is present.
*/
boolean hasNonEmptyValue(RelationalPersistentProperty property);
/** /**
* Contextualize this property value provider. * Contextualize this property value provider.
* *
@ -1072,6 +1085,8 @@ public class MappingRelationalConverter extends AbstractRelationalConverter
*/ */
boolean hasValue(AggregatePath path); boolean hasValue(AggregatePath path);
boolean hasNonEmptyValue(AggregatePath aggregatePath);
/** /**
* Determine whether there is a value for the given {@link SqlIdentifier}. * Determine whether there is a value for the given {@link SqlIdentifier}.
* *
@ -1154,6 +1169,11 @@ public class MappingRelationalConverter extends AbstractRelationalConverter
return accessor.hasValue(property); return accessor.hasValue(property);
} }
@Override
public boolean hasNonEmptyValue(RelationalPersistentProperty property) {
return hasValue(property);
}
@Nullable @Nullable
@Override @Override
public Object getValue(AggregatePath path) { public Object getValue(AggregatePath path) {
@ -1169,6 +1189,7 @@ public class MappingRelationalConverter extends AbstractRelationalConverter
@Override @Override
public boolean hasValue(AggregatePath path) { public boolean hasValue(AggregatePath path) {
Object value = document.get(path.getColumnInfo().alias().getReference()); Object value = document.get(path.getColumnInfo().alias().getReference());
if (value == null) { if (value == null) {
@ -1179,6 +1200,18 @@ public class MappingRelationalConverter extends AbstractRelationalConverter
return true; return true;
} }
return true;
}
@Override
public boolean hasNonEmptyValue(AggregatePath path) {
if (!hasValue(path)) {
return false;
}
Object value = document.get(path.getColumnInfo().alias().getReference());
if (value instanceof Collection<?> || value.getClass().isArray()) { if (value instanceof Collection<?> || value.getClass().isArray()) {
return !ObjectUtils.isEmpty(value); return !ObjectUtils.isEmpty(value);
} }

Loading…
Cancel
Save