Skip to content

DATAJDBC-352 - Support for embedded composite id. #219

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

Closed
wants to merge 4 commits into from
Closed
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>2.1.0-SNAPSHOT</version>
<version>2.1.0.DATAJDBC-352-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>2.1.0-SNAPSHOT</version>
<version>2.1.0.DATAJDBC-352-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>2.1.0-SNAPSHOT</version>
<version>2.1.0.DATAJDBC-352-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>2.1.0-SNAPSHOT</version>
<version>2.1.0.DATAJDBC-352-SNAPSHOT</version>
</parent>

<properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
* @author Jens Schauder
* @author Christoph Strobl
* @author Myeonghyeon Lee
* @author Yunyoung LEE
* @see MappingContext
* @see SimpleTypeHolder
* @see CustomConversions
Expand Down Expand Up @@ -436,7 +437,7 @@ private Iterable<Object> resolveRelation(@Nullable Object id, RelationalPersiste

Identifier identifier = id == null //
? this.identifier.withPart(rootPath.getQualifierColumn(), key, Object.class) //
: Identifier.of(rootPath.extendBy(property).getReverseColumnName(), id, Object.class);
: JdbcIdentifierBuilder.forBackReferences(BasicJdbcConverter.this, rootPath.extendBy(property), id).build();

PersistentPropertyPath<? extends RelationalPersistentProperty> propertyPath = path.extendBy(property)
.getRequiredPersistentPropertyPath();
Expand Down Expand Up @@ -512,6 +513,11 @@ private Object readEntityFrom(RelationalPersistentProperty property) {

if (idProperty != null) {
idValue = newContext.readFrom(idProperty);
} else if (property.isEmbedded()) {
return createInstance(entity, parameter -> {
RelationalPersistentProperty parameterProperty = entity.getRequiredPersistentProperty(parameter.getName());
return newContext.propertyValueProvider.getPropertyValue(parameterProperty);
});
} else {
idValue = backReferencePropertyValueProvider.getPropertyValue(property);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.relational.core.dialect.LockClause;
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
Expand Down Expand Up @@ -66,6 +65,7 @@
* @author Tyler Van Gorder
* @author Milan Milanov
* @author Myeonghyeon Lee
* @author Yunyoung LEE
* @since 1.1
*/
public class DefaultDataAccessStrategy implements DataAccessStrategy {
Expand Down Expand Up @@ -117,7 +117,7 @@ public <T> Object insert(T instance, Class<T> domainType, Identifier identifier)
if (idValue != null) {

RelationalPersistentProperty idProperty = persistentEntity.getRequiredIdProperty();
addConvertedPropertyValue(parameterSource, idProperty, idValue, idProperty.getColumnName());
addConvertedIdPropertyValue(parameterSource, idProperty, idValue, idProperty.getColumnName());
}

KeyHolder holder = new GeneratedKeyHolder();
Expand Down Expand Up @@ -218,7 +218,18 @@ public void delete(Object rootId, PersistentPropertyPath<RelationalPersistentPro
String delete = sql(rootEntity.getType()).createDeleteByPath(propertyPath);

SqlIdentifierParameterSource parameters = new SqlIdentifierParameterSource(getIdentifierProcessing());
parameters.addValue(ROOT_ID_PARAMETER, rootId);
if (referencingProperty.isEmbedded()) {

PersistentPropertyAccessor<Object> accessor = rootEntity.getPropertyAccessor(rootId);
for (RelationalPersistentProperty property : rootEntity) {
parameters.addValue(property.getColumnName(), accessor.getProperty(property));
}
} else {

parameters.addValue(new PersistentPropertyPathExtension(context, propertyPath).getEffectiveIdColumnName(),
rootId);
}

operations.update(delete, parameters);
}

Expand Down Expand Up @@ -322,13 +333,42 @@ public <T> Iterable<T> findAllById(Iterable<?> ids, Class<T> domainType) {
RelationalPersistentProperty idProperty = getRequiredPersistentEntity(domainType).getRequiredIdProperty();
SqlIdentifierParameterSource parameterSource = new SqlIdentifierParameterSource(getIdentifierProcessing());

addConvertedPropertyValuesAsList(parameterSource, idProperty, ids, IDS_SQL_PARAMETER);
if (idProperty.isEmbedded()) {

// NamedParamterUtils#substituteNamedParameters handles Object[] parameterSource as multiple parameter value
List<Object[]> idParameters = new ArrayList<>();
for (Object id : ids) {
List<Object> parameters = new ArrayList<>();
extractEmbeddedParameters(parameters, idProperty, id);
idParameters.add(parameters.toArray());
}

parameterSource.addValue(IDS_SQL_PARAMETER, idParameters);
} else {

addConvertedPropertyValuesAsList(parameterSource, idProperty, ids, IDS_SQL_PARAMETER);
}

String findAllInListSql = sql(domainType).getFindAllInList();

return operations.query(findAllInListSql, parameterSource, (RowMapper<T>) getEntityRowMapper(domainType));
}

private void extractEmbeddedParameters(List<Object> parameters, RelationalPersistentProperty property, Object value) {

if (property.isEmbedded()) {

final RelationalPersistentEntity<?> embeddedEntity = context.getPersistentEntity(property);
final PersistentPropertyAccessor<Object> embeddedAccessor = embeddedEntity.getPropertyAccessor(value);

embeddedEntity.doWithProperties((PropertyHandler<RelationalPersistentProperty>) embeddedProperty -> //
extractEmbeddedParameters(parameters, embeddedProperty, embeddedAccessor.getProperty(embeddedProperty)));
} else {

parameters.add(value);
}
}

/*
* (non-Javadoc)
* @see org.springframework.data.jdbc.core.RelationResolver#findAllByPath(org.springframework.data.jdbc.support.Identifier, org.springframework.data.mapping.PersistentPropertyPath)
Expand Down Expand Up @@ -496,7 +536,7 @@ private <T> SqlIdentifierParameterSource createIdParameterSource(Object id, Clas

SqlIdentifierParameterSource parameterSource = new SqlIdentifierParameterSource(getIdentifierProcessing());

addConvertedPropertyValue( //
addConvertedIdPropertyValue( //
parameterSource, //
getRequiredPersistentEntity(domainType).getRequiredIdProperty(), //
id, //
Expand All @@ -505,6 +545,23 @@ private <T> SqlIdentifierParameterSource createIdParameterSource(Object id, Clas
return parameterSource;
}

private void addConvertedIdPropertyValue(SqlIdentifierParameterSource parameterSource,
RelationalPersistentProperty property, Object value, SqlIdentifier defaultName) {

if (property.isEmbedded()) {
final RelationalPersistentEntity<?> embeddedEntity = context.getRequiredPersistentEntity(property);
final String prefix = property.getEmbeddedPrefix();

final PersistentPropertyAccessor<Object> propertyAccessor = embeddedEntity.getPropertyAccessor(value);
for (final RelationalPersistentProperty embeddedProperty : embeddedEntity) {
addConvertedIdPropertyValue(parameterSource, embeddedProperty, propertyAccessor.getProperty(embeddedProperty),
embeddedProperty.getColumnName().transform(prefix::concat));
}
} else {
addConvertedPropertyValue(parameterSource, property, value, defaultName);
}
}

private IdentifierProcessing getIdentifierProcessing() {
return sqlGeneratorSource.getDialect().getIdentifierProcessing();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,22 @@
*/
package org.springframework.data.jdbc.core.convert;

import java.util.Iterator;
import java.util.stream.StreamSupport;

import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

/**
* Builder for {@link Identifier}. Mainly for internal use within the framework
*
* @author Jens Schauder
* @author Yunyoung LEE
* @since 1.1
*/
public class JdbcIdentifierBuilder {
Expand All @@ -43,11 +51,29 @@ public static JdbcIdentifierBuilder empty() {
public static JdbcIdentifierBuilder forBackReferences(JdbcConverter converter, PersistentPropertyPathExtension path,
@Nullable Object value) {

Identifier identifier = Identifier.of( //
path.getReverseColumnName(), //
value, //
converter.getColumnType(path.getIdDefiningParentPath().getRequiredIdProperty()) //
);
Identifier identifier = null;

RelationalPersistentEntity<?> entity = converter.getMappingContext().getPersistentEntity(value.getClass());
if (entity != null) {

PersistentPropertyAccessor<Object> accessor = entity.getPropertyAccessor(value);

Iterator<SqlIdentifier> reverseColumnNames = path.getReverseColumnNames().iterator();

identifier = Identifier.empty();
for (RelationalPersistentProperty property : entity) {
Assert.state(reverseColumnNames.hasNext(), "no reverse column name for " + property.getName());
identifier = identifier.withPart(reverseColumnNames.next(), accessor.getProperty(property),
converter.getColumnType(property));
}
} else {

identifier = Identifier.of( //
path.getReverseColumnName(), //
value, //
converter.getColumnType(path.getIdDefiningParentPath().getRequiredIdProperty()) //
);
}

return new JdbcIdentifierBuilder(identifier);
}
Expand Down
Loading