DATAJDBC-259 - Polishing.
Unwrap multi-dimensional array types to determine the proper component type. Extend tests. Inline isCollectionOf[Entities|SimpleType]Like calls and remove utility methods on RelationalPersistentProperty as the usage-scope is specific to array handling. Original pull request: #113.
This commit is contained in:
@@ -81,7 +81,7 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
this.accessStrategy = this;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.jdbc.core.DataAccessStrategy#insert(java.lang.Object, java.lang.Class, java.util.Map)
|
||||
*/
|
||||
@@ -320,7 +320,11 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
return convertedValue;
|
||||
}
|
||||
|
||||
Class<?> componentType = convertedValue.getClass().getComponentType();
|
||||
Class<?> componentType = convertedValue.getClass();
|
||||
while (componentType.isArray()) {
|
||||
componentType = componentType.getComponentType();
|
||||
}
|
||||
|
||||
String typeName = JDBCType.valueOf(JdbcUtil.sqlTypeFor(componentType)).getName();
|
||||
|
||||
return operations.getJdbcOperations().execute(
|
||||
|
||||
@@ -110,7 +110,7 @@ public class EntityRowMapper<T> implements RowMapper<T> {
|
||||
private Object readOrLoadProperty(ResultSet resultSet, @Nullable Object id, RelationalPersistentProperty property,
|
||||
String prefix) {
|
||||
|
||||
if (property.isCollectionOfEntitiesLike() && id != null) {
|
||||
if (property.isCollectionLike() && property.isEntity() && id != null) {
|
||||
return accessStrategy.findAllByProperty(id, property);
|
||||
} else if (property.isMap() && id != null) {
|
||||
return ITERABLE_OF_ENTRY_TO_MAP_CONVERTER.convert(accessStrategy.findAllByProperty(id, property));
|
||||
|
||||
@@ -56,6 +56,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
*
|
||||
* @author Jens Schauder
|
||||
* @author Thomas Lang
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@Transactional
|
||||
@@ -347,6 +348,31 @@ public class JdbcAggregateTemplateIntegrationTests {
|
||||
assertThat(reloaded.digits).isEqualTo(new String[] { "one", "two", "three" });
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-259
|
||||
public void saveAndLoadAnEntityWithMultidimensionalArray() {
|
||||
|
||||
// MySQL and other do not support array datatypes. See
|
||||
// https://dev.mysql.com/doc/refman/8.0/en/data-type-overview.html
|
||||
assumeNot("mysql");
|
||||
assumeNot("mariadb");
|
||||
assumeNot("mssql");
|
||||
assumeNot("hsqldb");
|
||||
|
||||
ArrayOwner arrayOwner = new ArrayOwner();
|
||||
arrayOwner.multidimensional = new String[][] { { "one-a", "two-a", "three-a" }, { "one-b", "two-b", "three-b" } };
|
||||
|
||||
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.multidimensional)
|
||||
.isEqualTo(new String[][] { { "one-a", "two-a", "three-a" }, { "one-b", "two-b", "three-b" } });
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-259
|
||||
public void saveAndLoadAnEntityWithList() {
|
||||
|
||||
@@ -404,6 +430,7 @@ public class JdbcAggregateTemplateIntegrationTests {
|
||||
@Id Long id;
|
||||
|
||||
String[] digits;
|
||||
String[][] multidimensional;
|
||||
}
|
||||
|
||||
@Table("ARRAY_OWNER")
|
||||
|
||||
@@ -10,4 +10,4 @@ CREATE TABLE Child_No_Id (ONE_TO_ONE_PARENT INTEGER PRIMARY KEY, content VARCHAR
|
||||
CREATE TABLE LIST_PARENT ( id4 BIGINT GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ) PRIMARY KEY, NAME VARCHAR(100));
|
||||
CREATE TABLE element_no_id ( content VARCHAR(100), LIST_PARENT_key BIGINT, LIST_PARENT BIGINT);
|
||||
|
||||
CREATE TABLE ARRAY_OWNER (ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, DIGITS VARCHAR(20) ARRAY[10] NOT NULL);
|
||||
CREATE TABLE ARRAY_OWNER (ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, DIGITS VARCHAR(20) ARRAY[10] NOT NULL, MULTIDIMENSIONAL VARCHAR(20) ARRAY[10] NULL);
|
||||
|
||||
@@ -13,4 +13,4 @@ CREATE TABLE Child_No_Id (ONE_TO_ONE_PARENT INTEGER PRIMARY KEY, content VARCHAR
|
||||
CREATE TABLE LIST_PARENT ( id4 SERIAL PRIMARY KEY, NAME VARCHAR(100));
|
||||
CREATE TABLE element_no_id ( content VARCHAR(100), LIST_PARENT_key BIGINT, LIST_PARENT INTEGER);
|
||||
|
||||
CREATE TABLE ARRAY_OWNER (ID SERIAL PRIMARY KEY, DIGITS VARCHAR(20) ARRAY[10] NOT NULL);
|
||||
CREATE TABLE ARRAY_OWNER (ID SERIAL PRIMARY KEY, DIGITS VARCHAR(20)[10], MULTIDIMENSIONAL VARCHAR(20)[10][10]);
|
||||
|
||||
@@ -60,6 +60,7 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent
|
||||
private final Lazy<Optional<String>> keyColumnName;
|
||||
private final Lazy<Boolean> isEmbedded;
|
||||
private final Lazy<String> embeddedPrefix;
|
||||
private final Lazy<Class<?>> columnType = Lazy.of(this::doGetColumnType);
|
||||
|
||||
/**
|
||||
* Creates a new {@link AnnotationBasedPersistentProperty}.
|
||||
@@ -130,9 +131,12 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent
|
||||
*
|
||||
* @return a {@link Class} that is suitable for usage with JDBC drivers
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Class getColumnType() {
|
||||
public Class<?> getColumnType() {
|
||||
return columnType.get();
|
||||
}
|
||||
|
||||
private Class<?> doGetColumnType() {
|
||||
|
||||
if (isReference()) {
|
||||
return columnTypeForReference();
|
||||
@@ -146,7 +150,11 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent
|
||||
|
||||
Class componentColumnType = columnTypeForNonEntity(getActualType());
|
||||
|
||||
if (isCollectionOfSimpleTypeLike()) {
|
||||
while (componentColumnType.isArray()) {
|
||||
componentColumnType = componentColumnType.getComponentType();
|
||||
}
|
||||
|
||||
if (isCollectionLike() && !isEntity()) {
|
||||
return Array.newInstance(componentColumnType, 0).getClass();
|
||||
}
|
||||
|
||||
|
||||
@@ -37,9 +37,11 @@ public interface RelationalPersistentProperty extends PersistentProperty<Relatio
|
||||
String getColumnName();
|
||||
|
||||
/**
|
||||
* The type to be used to store this property in the database.
|
||||
* The type to be used to store this property in the database. Multidimensional arrays are unwrapped to reflect a
|
||||
* top-level array type (e.g. {@code String[][]} returns {@code String[]}).
|
||||
*
|
||||
* @return a {@link Class} that is suitable for usage with JDBC drivers.
|
||||
* @see org.springframework.data.jdbc.support.JdbcUtil#sqlTypeFor(Class)
|
||||
*/
|
||||
Class<?> getColumnType();
|
||||
|
||||
@@ -84,12 +86,4 @@ public interface RelationalPersistentProperty extends PersistentProperty<Relatio
|
||||
default String getEmbeddedPrefix() {
|
||||
return null;
|
||||
};
|
||||
|
||||
default boolean isCollectionOfEntitiesLike() {
|
||||
return isCollectionLike() && isEntity();
|
||||
}
|
||||
|
||||
default boolean isCollectionOfSimpleTypeLike() {
|
||||
return isCollectionLike() && !isEntity();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,18 +134,18 @@ public class BasicRelationalPersistentPropertyUnitTests {
|
||||
|
||||
SoftAssertions softly = new SoftAssertions();
|
||||
|
||||
softly.assertThat(listOfString.isCollectionOfSimpleTypeLike())
|
||||
softly.assertThat(listOfString.isCollectionLike() && !listOfString.isEntity())
|
||||
.describedAs("listOfString is a Collection of a simple type.").isEqualTo(true);
|
||||
softly.assertThat(arrayOfString.isCollectionOfSimpleTypeLike())
|
||||
softly.assertThat(arrayOfString.isCollectionLike() && !arrayOfString.isEntity())
|
||||
.describedAs("arrayOfString is a Collection of a simple type.").isTrue();
|
||||
softly.assertThat(listOfEntity.isCollectionOfSimpleTypeLike())
|
||||
softly.assertThat(listOfEntity.isCollectionLike() && !listOfEntity.isEntity())
|
||||
.describedAs("listOfEntity is a Collection of a simple type.").isFalse();
|
||||
softly.assertThat(arrayOfEntity.isCollectionOfSimpleTypeLike())
|
||||
softly.assertThat(arrayOfEntity.isCollectionLike() && !arrayOfEntity.isEntity())
|
||||
.describedAs("arrayOfEntity is a Collection of a simple type.").isFalse();
|
||||
|
||||
BiConsumer<RelationalPersistentProperty, String> checkEitherOr = (p, s) -> softly
|
||||
.assertThat(p.isCollectionOfSimpleTypeLike()).describedAs(s + " contains either simple types or entities")
|
||||
.isNotEqualTo(p.isCollectionOfEntitiesLike());
|
||||
.assertThat(p.isCollectionLike() && !p.isEntity()).describedAs(s + " contains either simple types or entities")
|
||||
.isNotEqualTo(p.isCollectionLike() && p.isEntity());
|
||||
|
||||
checkEitherOr.accept(listOfString,"listOfString");
|
||||
checkEitherOr.accept(arrayOfString,"arrayOfString");
|
||||
|
||||
Reference in New Issue
Block a user