Skip to content

Supported nested conversions for AggregateReference. #2062

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-relational-parent</artifactId>
<version>4.0.0-SNAPSHOT</version>
<version>4.0.0-1828-aggregate-ref-with-convertable-SNAPSHOT</version>
<packaging>pom</packaging>

<name>Spring Data Relational Parent</name>
Expand Down
2 changes: 1 addition & 1 deletion spring-data-jdbc-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-relational-parent</artifactId>
<version>4.0.0-SNAPSHOT</version>
<version>4.0.0-1828-aggregate-ref-with-convertable-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
4 changes: 2 additions & 2 deletions spring-data-jdbc/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<modelVersion>4.0.0</modelVersion>

<artifactId>spring-data-jdbc</artifactId>
<version>4.0.0-SNAPSHOT</version>
<version>4.0.0-1828-aggregate-ref-with-convertable-SNAPSHOT</version>

<name>Spring Data JDBC</name>
<description>Spring Data module for JDBC repositories.</description>
Expand All @@ -15,7 +15,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-relational-parent</artifactId>
<version>4.0.0-SNAPSHOT</version>
<version>4.0.0-1828-aggregate-ref-with-convertable-SNAPSHOT</version>
</parent>

<properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterRegistry;
import org.springframework.data.convert.CustomConversions;
import org.springframework.data.jdbc.core.mapping.AggregateReference;
import org.springframework.data.jdbc.core.mapping.JdbcValue;
Expand Down Expand Up @@ -80,7 +78,7 @@ public class MappingJdbcConverter extends MappingRelationalConverter implements
* {@link #MappingJdbcConverter(RelationalMappingContext, RelationResolver, CustomConversions, JdbcTypeFactory)}
* (MappingContext, RelationResolver, JdbcTypeFactory)} to convert arrays and large objects into JDBC-specific types.
*
* @param context must not be {@literal null}.
* @param context must not be {@literal null}.
* @param relationResolver used to fetch additional relations from the database. Must not be {@literal null}.
*/
public MappingJdbcConverter(RelationalMappingContext context, RelationResolver relationResolver) {
Expand All @@ -91,19 +89,17 @@ public MappingJdbcConverter(RelationalMappingContext context, RelationResolver r

this.typeFactory = JdbcTypeFactory.unsupported();
this.relationResolver = relationResolver;

registerAggregateReferenceConverters();
}

/**
* Creates a new {@link MappingJdbcConverter} given {@link MappingContext}.
*
* @param context must not be {@literal null}.
* @param context must not be {@literal null}.
* @param relationResolver used to fetch additional relations from the database. Must not be {@literal null}.
* @param typeFactory must not be {@literal null}
* @param typeFactory must not be {@literal null}
*/
public MappingJdbcConverter(RelationalMappingContext context, RelationResolver relationResolver,
CustomConversions conversions, JdbcTypeFactory typeFactory) {
CustomConversions conversions, JdbcTypeFactory typeFactory) {

super(context, conversions);

Expand All @@ -112,14 +108,6 @@ public MappingJdbcConverter(RelationalMappingContext context, RelationResolver r

this.typeFactory = typeFactory;
this.relationResolver = relationResolver;

registerAggregateReferenceConverters();
}

private void registerAggregateReferenceConverters() {

ConverterRegistry registry = (ConverterRegistry) getConversionService();
AggregateReferenceConverters.getConvertersToRegister(getConversionService()).forEach(registry::addConverter);
}

@Nullable
Expand Down Expand Up @@ -185,33 +173,48 @@ private Class<?> doGetColumnType(RelationalPersistentProperty property) {
}

@Override
@Nullable
public Object readValue(@Nullable Object value, TypeInformation<?> type) {

if (value == null) {
return value;
}
protected Object readTechnologyType(Object value) {

if (value instanceof Array array) {
try {
return super.readValue(array.getArray(), type);
} catch (SQLException | ConverterNotFoundException e) {
return array.getArray();
} catch (SQLException e) {
LOG.info("Failed to extract a value of type %s from an Array; Attempting to use standard conversions", e);

}
}

return super.readValue(value, type);
return value;
}

@Override
protected TypeInformation<?> determineModuleReadTarget(TypeInformation<?> ultimateTargetType) {

if (AggregateReference.class.isAssignableFrom(ultimateTargetType.getType())) {
// the id type of a AggregateReference
return ultimateTargetType.getTypeArguments().get(1);
}
return ultimateTargetType;
}

@Override
protected Object readModuleType(Object value, TypeInformation<?> targetType) {

if (AggregateReference.class.isAssignableFrom(targetType.getType())) {
return AggregateReference.to(value);
}
return value;
}

@Nullable
public Object writeValue(@Nullable Object value, TypeInformation<?> type) {
@Override
protected Object getPotentiallyConvertedSimpleWrite(Object value, TypeInformation<?> type) {

if (value == null) {
return null;
if (value instanceof AggregateReference<?, ?> aggregateReference) {
return writeValue(aggregateReference.getId(), type);
}

return super.writeValue(value, type);
return super.getPotentiallyConvertedSimpleWrite(value, type);
}

private boolean canWriteAsJdbcValue(@Nullable Object value) {
Expand Down Expand Up @@ -285,7 +288,7 @@ public <R> R readAndResolve(TypeInformation<R> type, RowDocument source, Identif

@Override
protected RelationalPropertyValueProvider newValueProvider(RowDocumentAccessor documentAccessor,
ValueExpressionEvaluator evaluator, ConversionContext context) {
ValueExpressionEvaluator evaluator, ConversionContext context) {

if (context instanceof ResolvingConversionContext rcc) {

Expand Down Expand Up @@ -314,7 +317,7 @@ class ResolvingRelationalPropertyValueProvider implements RelationalPropertyValu
private final Identifier identifier;

private ResolvingRelationalPropertyValueProvider(AggregatePathValueProvider delegate, RowDocumentAccessor accessor,
ResolvingConversionContext context, Identifier identifier) {
ResolvingConversionContext context, Identifier identifier) {

AggregatePath path = context.aggregatePath();

Expand All @@ -323,15 +326,15 @@ private ResolvingRelationalPropertyValueProvider(AggregatePathValueProvider dele
this.context = context;
this.identifier = path.isEntity()
? potentiallyAppendIdentifier(identifier, path.getRequiredLeafEntity(),
property -> delegate.getValue(path.append(property)))
property -> delegate.getValue(path.append(property)))
: identifier;
}

/**
* Conditionally append the identifier if the entity has an identifier property.
*/
static Identifier potentiallyAppendIdentifier(Identifier base, RelationalPersistentEntity<?> entity,
Function<RelationalPersistentProperty, Object> getter) {
Function<RelationalPersistentProperty, Object> getter) {

if (entity.hasIdProperty()) {

Expand Down Expand Up @@ -460,7 +463,7 @@ public RelationalPropertyValueProvider withContext(ConversionContext context) {

return context == this.context ? this
: new ResolvingRelationalPropertyValueProvider(delegate.withContext(context), accessor,
(ResolvingConversionContext) context, identifier);
(ResolvingConversionContext) context, identifier);
}
}

Expand All @@ -472,7 +475,7 @@ public RelationalPropertyValueProvider withContext(ConversionContext context) {
* @param identifier
*/
private record ResolvingConversionContext(ConversionContext delegate, AggregatePath aggregatePath,
Identifier identifier) implements ConversionContext {
Identifier identifier) implements ConversionContext {

@Override
public <S> S convert(Object source, TypeInformation<? extends S> typeHint) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@
*
* @author Jens Schauder
*/
public class BasicRelationalConverterAggregateReferenceUnitTests {
class MappingJdbcConverterAggregateReferenceUnitTests {

JdbcMappingContext context = new JdbcMappingContext();
JdbcConverter converter = new MappingJdbcConverter(context, mock(RelationResolver.class));

RelationalPersistentEntity<?> entity = context.getRequiredPersistentEntity(DummyEntity.class);

@Test // DATAJDBC-221
public void convertsToAggregateReference() {
void convertsToAggregateReference() {

final RelationalPersistentProperty property = entity.getRequiredPersistentProperty("reference");

Expand All @@ -51,7 +51,7 @@ public void convertsToAggregateReference() {
}

@Test // DATAJDBC-221
public void convertsFromAggregateReference() {
void convertsFromAggregateReference() {

final RelationalPersistentProperty property = entity.getRequiredPersistentProperty("reference");

Expand Down
Loading