Browse Source

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.
pull/117/head
Mark Paluch 7 years ago
parent
commit
3b6f01f83e
  1. 8
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java
  2. 2
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/EntityRowMapper.java
  3. 27
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateIntegrationTests.java
  4. 2
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-hsql.sql
  5. 2
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-postgres.sql
  6. 14
      spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentProperty.java
  7. 12
      spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/RelationalPersistentProperty.java
  8. 12
      spring-data-relational/src/test/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentPropertyUnitTests.java

8
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java

@ -81,7 +81,7 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy { @@ -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 { @@ -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(

2
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/EntityRowMapper.java

@ -110,7 +110,7 @@ public class EntityRowMapper<T> implements RowMapper<T> { @@ -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));

27
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateIntegrationTests.java

@ -56,6 +56,7 @@ import org.springframework.transaction.annotation.Transactional; @@ -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 { @@ -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 { @@ -404,6 +430,7 @@ public class JdbcAggregateTemplateIntegrationTests {
@Id Long id;
String[] digits;
String[][] multidimensional;
}
@Table("ARRAY_OWNER")

2
spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-hsql.sql

@ -10,4 +10,4 @@ CREATE TABLE Child_No_Id (ONE_TO_ONE_PARENT INTEGER PRIMARY KEY, content VARCHAR @@ -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);

2
spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-postgres.sql

@ -13,4 +13,4 @@ CREATE TABLE Child_No_Id (ONE_TO_ONE_PARENT INTEGER PRIMARY KEY, content VARCHAR @@ -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]);

14
spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentProperty.java

@ -60,6 +60,7 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent @@ -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 @@ -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 @@ -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();
}

12
spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/RelationalPersistentProperty.java

@ -37,9 +37,11 @@ public interface RelationalPersistentProperty extends PersistentProperty<Relatio @@ -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 @@ -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();
}
}

12
spring-data-relational/src/test/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentPropertyUnitTests.java

@ -134,18 +134,18 @@ public class BasicRelationalPersistentPropertyUnitTests { @@ -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");

Loading…
Cancel
Save