DATAJDBC-130 - Support entities with List valued properties.
This commit is contained in:
committed by
Greg Turnquist
parent
7ed2ed7d7e
commit
f5de195768
@@ -200,11 +200,11 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
|
||||
Class<?> actualType = property.getActualType();
|
||||
String findAllByProperty = sql(actualType).getFindAllByProperty(property.getReverseColumnName(),
|
||||
property.getKeyColumn());
|
||||
property.getKeyColumn(), property.isOrdered());
|
||||
|
||||
MapSqlParameterSource parameter = new MapSqlParameterSource(property.getReverseColumnName(), rootId);
|
||||
|
||||
return (Iterable<T>) operations.query(findAllByProperty, parameter, property.isQualified() //
|
||||
return (Iterable<T>) operations.query(findAllByProperty, parameter, property.isMap() //
|
||||
? getMapEntityRowMapper(property) //
|
||||
: getEntityRowMapper(actualType));
|
||||
}
|
||||
|
||||
@@ -19,10 +19,8 @@ import lombok.NonNull;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.convert.ClassGeneratingEntityInstantiator;
|
||||
import org.springframework.data.convert.EntityInstantiator;
|
||||
import org.springframework.data.jdbc.mapping.model.JdbcMappingContext;
|
||||
@@ -45,6 +43,8 @@ import org.springframework.jdbc.core.RowMapper;
|
||||
*/
|
||||
public class EntityRowMapper<T> implements RowMapper<T> {
|
||||
|
||||
private static final Converter ITERABLE_OF_ENTRY_TO_MAP_CONVERTER = new IterableOfEntryToMapConverter();
|
||||
|
||||
private final JdbcPersistentEntity<T> entity;
|
||||
private final EntityInstantiator instantiator = new ClassGeneratingEntityInstantiator();
|
||||
private final ConversionService conversions;
|
||||
@@ -79,13 +79,12 @@ public class EntityRowMapper<T> implements RowMapper<T> {
|
||||
|
||||
for (JdbcPersistentProperty property : entity) {
|
||||
|
||||
if (Set.class.isAssignableFrom(property.getType())) {
|
||||
if (property.isCollectionLike()) {
|
||||
propertyAccessor.setProperty(property, accessStrategy.findAllByProperty(id, property));
|
||||
} else if (Map.class.isAssignableFrom(property.getType())) {
|
||||
} else if (property.isMap()) {
|
||||
|
||||
Iterable<Object> allByProperty = accessStrategy.findAllByProperty(id, property);
|
||||
IterableOfEntryToMapConverter converter = new IterableOfEntryToMapConverter();
|
||||
propertyAccessor.setProperty(property, converter.convert(allByProperty));
|
||||
propertyAccessor.setProperty(property, ITERABLE_OF_ENTRY_TO_MAP_CONVERTER.convert(allByProperty));
|
||||
} else {
|
||||
propertyAccessor.setProperty(property, readFrom(resultSet, property, ""));
|
||||
}
|
||||
|
||||
@@ -95,17 +95,22 @@ class SqlGenerator {
|
||||
* a referencing entity.
|
||||
*
|
||||
* @param columnName name of the column of the FK back to the referencing entity.
|
||||
* @param keyColumn if the property is of type {@link Map} this column contains the map key.
|
||||
* @param keyColumn if the property is of type {@link Map} this column contains the map key.
|
||||
* @param ordered whether the SQL statement should include an ORDER BY for the keyColumn. If this is {@literal true}, the keyColumn must not be {@literal null}.
|
||||
* @return a SQL String.
|
||||
*/
|
||||
String getFindAllByProperty(String columnName, String keyColumn) {
|
||||
String getFindAllByProperty(String columnName, String keyColumn, boolean ordered) {
|
||||
|
||||
Assert.isTrue(keyColumn != null || !ordered, "If the SQL statement should be ordered a keyColumn to order by must be provided.");
|
||||
|
||||
String baseSelect = (keyColumn != null) //
|
||||
? createSelectBuilder().column(cb -> cb.tableAlias(entity.getTableName()).column(keyColumn).as(keyColumn))
|
||||
.build()
|
||||
.build()
|
||||
: getFindAll();
|
||||
|
||||
return String.format("%s WHERE %s = :%s", baseSelect, columnName, columnName);
|
||||
String orderBy = ordered ? " ORDER BY " + keyColumn : "";
|
||||
|
||||
return String.format("%s WHERE %s = :%s%s", baseSelect, columnName, columnName, orderBy);
|
||||
}
|
||||
|
||||
String getExists() {
|
||||
|
||||
@@ -16,12 +16,6 @@
|
||||
package org.springframework.data.jdbc.core.conversion;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.data.jdbc.core.conversion.DbAction.Insert;
|
||||
import org.springframework.data.jdbc.core.conversion.DbAction.Update;
|
||||
import org.springframework.data.jdbc.mapping.model.JdbcMappingContext;
|
||||
@@ -33,6 +27,13 @@ import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
import org.springframework.data.util.StreamUtils;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Converts an entity that is about to be saved into {@link DbAction}s inside a {@link AggregateChange} that need to be
|
||||
* executed against the database to recreate the appropriate state in the database.
|
||||
@@ -157,6 +158,10 @@ public class JdbcEntityWriter extends JdbcEntityWriterSupport {
|
||||
|
||||
Class<?> type = p.getType();
|
||||
|
||||
if (List.class.isAssignableFrom(type)) {
|
||||
return listPropertyAsStream(p, propertyAccessor);
|
||||
}
|
||||
|
||||
if (Collection.class.isAssignableFrom(type)) {
|
||||
return collectionPropertyAsStream(p, propertyAccessor);
|
||||
}
|
||||
@@ -178,6 +183,21 @@ public class JdbcEntityWriter extends JdbcEntityWriterSupport {
|
||||
: ((Collection<Object>) property).stream();
|
||||
}
|
||||
|
||||
private Stream<Object> listPropertyAsStream(JdbcPersistentProperty p, PersistentPropertyAccessor propertyAccessor) {
|
||||
|
||||
Object property = propertyAccessor.getProperty(p);
|
||||
|
||||
if (property == null) return Stream.empty();
|
||||
|
||||
List<Object> listProperty = (List<Object>) property;
|
||||
HashMap<Integer, Object> map = new HashMap<>();
|
||||
for (int i = 0; i < listProperty.size(); i++) {
|
||||
map.put(i, listProperty.get(i));
|
||||
}
|
||||
|
||||
return map.entrySet().stream().map(e -> (Object) e);
|
||||
}
|
||||
|
||||
private Stream<Object> mapPropertyAsStream(JdbcPersistentProperty p, PersistentPropertyAccessor propertyAccessor) {
|
||||
|
||||
Object property = propertyAccessor.getProperty(p);
|
||||
|
||||
@@ -15,12 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.jdbc.mapping.model;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
|
||||
@@ -29,6 +23,13 @@ import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Meta data about a property to be used by repository implementations.
|
||||
*
|
||||
@@ -114,7 +115,16 @@ public class BasicJdbcPersistentProperty extends AnnotationBasedPersistentProper
|
||||
|
||||
@Override
|
||||
public boolean isQualified() {
|
||||
return isMap();
|
||||
return isMap() || isListLike();
|
||||
}
|
||||
|
||||
private boolean isListLike() {
|
||||
return isCollectionLike() && !Set.class.isAssignableFrom(this.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOrdered() {
|
||||
return isListLike();
|
||||
}
|
||||
|
||||
private Class columnTypeIfEntity(Class type) {
|
||||
|
||||
@@ -51,4 +51,9 @@ public interface JdbcPersistentProperty extends PersistentProperty<JdbcPersisten
|
||||
* Returns if this property is a qualified property, i.e. a property referencing multiple elements that can get picked by a key or an index.
|
||||
*/
|
||||
boolean isQualified();
|
||||
|
||||
/**
|
||||
* Returns whether this property is an ordered property.
|
||||
*/
|
||||
boolean isOrdered();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user