diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverter.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverter.java index b64fcff53..8d6919c5c 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverter.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverter.java @@ -173,13 +173,15 @@ public class MappingCassandraConverter extends AbstractCassandraConverter * {@link CassandraPersistentEntity entity}. * @see org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity */ - private ConvertingPropertyAccessor newConvertingPropertyAccessor(Object source, CassandraPersistentEntity entity) { + @SuppressWarnings("unchecked") + private ConvertingPropertyAccessor newConvertingPropertyAccessor(S source, + CassandraPersistentEntity entity) { PersistentPropertyAccessor propertyAccessor = source instanceof PersistentPropertyAccessor ? (PersistentPropertyAccessor) source : entity.getPropertyAccessor(source); - return new ConvertingPropertyAccessor(propertyAccessor, getConversionService()); + return new ConvertingPropertyAccessor<>(propertyAccessor, getConversionService()); } private PersistentEntityParameterValueProvider newParameterValueProvider( @@ -247,28 +249,33 @@ public class MappingCassandraConverter extends AbstractCassandraConverter } private S readEntityFromRow(CassandraPersistentEntity entity, Row row) { - return doRead(entity, row, expressionEvaluator -> new BasicCassandraRowValueProvider(row, expressionEvaluator)); + return doReadEntity(entity, row, + expressionEvaluator -> new BasicCassandraRowValueProvider(row, expressionEvaluator)); } private S readEntityFromTuple(CassandraPersistentEntity entity, TupleValue tupleValue) { - return doRead(entity, tupleValue, + return doReadEntity(entity, tupleValue, expressionEvaluator -> new CassandraTupleValueProvider(tupleValue, getCodecRegistry(), expressionEvaluator)); } private S readEntityFromUdt(CassandraPersistentEntity entity, UDTValue udtValue) { - return doRead(entity, udtValue, + return doReadEntity(entity, udtValue, expressionEvaluator -> new CassandraUDTValueProvider(udtValue, getCodecRegistry(), expressionEvaluator)); } - private S doRead(CassandraPersistentEntity entity, V value, + private S doReadEntity(CassandraPersistentEntity entity, Object value, Function valueProviderSupplier) { SpELExpressionEvaluator expressionEvaluator = new DefaultSpELExpressionEvaluator(value, this.spELContext); - CassandraValueProvider valueProvider = valueProviderSupplier.apply(expressionEvaluator); + return doReadEntity(entity, valueProvider); + } + + private S doReadEntity(CassandraPersistentEntity entity, CassandraValueProvider valueProvider) { + PersistentEntityParameterValueProvider parameterValueProvider = newParameterValueProvider( entity, valueProvider); @@ -276,10 +283,14 @@ public class MappingCassandraConverter extends AbstractCassandraConverter S instance = instantiator.createInstance(entity, parameterValueProvider); - ConvertingPropertyAccessor propertyAccessor = newConvertingPropertyAccessor(instance, entity); - readProperties(entity, valueProvider, propertyAccessor); + if (entity.requiresPropertyPopulation()) { + ConvertingPropertyAccessor propertyAccessor = newConvertingPropertyAccessor(instance, entity); - return (S) propertyAccessor.getBean(); + readProperties(entity, valueProvider, propertyAccessor); + return propertyAccessor.getBean(); + } + + return instance; } private void readProperties(CassandraPersistentEntity entity, CassandraValueProvider valueProvider, @@ -298,38 +309,9 @@ public class MappingCassandraConverter extends AbstractCassandraConverter return; } - if (property.isCompositePrimaryKey()) { - - CassandraPersistentEntity keyEntity = getMappingContext().getRequiredPersistentEntity(property); - - Object key = propertyAccessor.getProperty(property); - - if (key == null) { - key = instantiatePrimaryKey(keyEntity, property, valueProvider); - } - - // now recurse on using the key this time - ConvertingPropertyAccessor pkPropertyAccessor = newConvertingPropertyAccessor(key, keyEntity); - readProperties(keyEntity, valueProvider, pkPropertyAccessor); - - // now that the key's properties have been populated, set the key property on the entity - propertyAccessor.setProperty(property, pkPropertyAccessor.getBean()); - - return; + if (property.isCompositePrimaryKey() || valueProvider.hasProperty(property)) { + propertyAccessor.setProperty(property, getReadValue(valueProvider, property)); } - - if (!valueProvider.hasProperty(property)) { - return; - } - - propertyAccessor.setProperty(property, getReadValue(valueProvider, property)); - } - - private Object instantiatePrimaryKey(CassandraPersistentEntity entity, CassandraPersistentProperty keyProperty, - CassandraValueProvider propertyProvider) { - - return this.instantiators.getInstantiatorFor(entity).createInstance(entity, - newParameterValueProvider(entity, propertyProvider)); } /* (non-Javadoc) @@ -687,7 +669,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter } // if the class doesn't have an id property, then it's using MapId - final MapId id = BasicMapId.id(); + MapId id = BasicMapId.id(); for (CassandraPersistentProperty property : entity) { @@ -954,8 +936,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter if (property.isCompositePrimaryKey()) { CassandraPersistentEntity keyEntity = getMappingContext().getRequiredPersistentEntity(property); - - return instantiatePrimaryKey(keyEntity, property, valueProvider); + return doReadEntity(keyEntity, valueProvider); } Object value = valueProvider.getPropertyValue(property); diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverterUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverterUnitTests.java index 9b1336898..3f9694c42 100755 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverterUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/convert/MappingCassandraConverterUnitTests.java @@ -822,6 +822,20 @@ public class MappingCassandraConverterUnitTests { assertThat(result.id.localDate).isEqualTo(java.time.LocalDate.of(2017, 1, 2)); } + @Test // DATACASS-672 + public void shouldReadTypeCompositePrimaryKeyUsingEntityInstantiatorAndPropertyPopulationInKeyCorrectly() { + + // condition, localDate + Row row = RowMockUtil.newRowMock(column("firstname", "Walter", DataType.varchar()), + column("lastname", "White", DataType.varchar())); + + TableWithCompositeKeyViaConstructor result = mappingCassandraConverter + .read(TableWithCompositeKeyViaConstructor.class, row); + + assertThat(result.key.firstname).isEqualTo("Walter"); + assertThat(result.key.lastname).isEqualTo("White"); + } + @Test // DATACASS-308 public void shouldWriteWhereConditionForTypeWithPkClassKeyUsingMapId() { @@ -1136,6 +1150,20 @@ public class MappingCassandraConverterUnitTests { MINT, USED } + @PrimaryKeyClass + public static class CompositeKeyWithPropertyAccessors { + + @PrimaryKeyColumn(type = PrimaryKeyType.PARTITIONED) String firstname; + @PrimaryKeyColumn String lastname; + } + + @Table + @RequiredArgsConstructor + public static class TableWithCompositeKeyViaConstructor { + + @PrimaryKey private final CompositeKeyWithPropertyAccessors key; + } + @Table public static class TypeWithLocalDate {