Skip to content
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
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jdbc</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<version>1.0.0.DATAJDBC-145-SNAPSHOT</version>

<name>Spring Data JDBC</name>
<description>Spring Data module for JDBC repositories.</description>
Expand All @@ -15,14 +15,14 @@
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<version>2.1.0.BUILD-SNAPSHOT</version>
</parent>

<properties>

<dist.key>DATAJDBC</dist.key>

<springdata.commons>2.0.0.BUILD-SNAPSHOT</springdata.commons>
<springdata.commons>2.1.0.BUILD-SNAPSHOT</springdata.commons>
<java-module-name>spring.data.jdbc</java-module-name>

<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import org.springframework.data.jdbc.core.conversion.Interpreter;
import org.springframework.data.jdbc.mapping.model.JdbcMappingContext;
import org.springframework.data.jdbc.mapping.model.JdbcPersistentEntity;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.util.Assert;

/**
* {@link Interpreter} for {@link DbAction}s using a {@link DataAccessStrategy} for performing actual database
Expand Down Expand Up @@ -60,15 +62,15 @@ public <T> void interpret(Delete<T> delete) {
if (delete.getPropertyPath() == null) {
accessStrategy.delete(delete.getRootId(), delete.getEntityType());
} else {
accessStrategy.delete(delete.getRootId(), delete.getPropertyPath());
accessStrategy.delete(delete.getRootId(), delete.getPropertyPath().getPath());
}
}

@Override
public <T> void interpret(DeleteAll<T> delete) {

if (delete.getEntityType() == null) {
accessStrategy.deleteAll(delete.getPropertyPath());
accessStrategy.deleteAll(delete.getPropertyPath().getPath());
} else {
accessStrategy.deleteAll(delete.getEntityType());
}
Expand All @@ -84,16 +86,32 @@ private <T> Map<String, Object> createAdditionalColumnValues(Insert<T> insert) {
}

private <T> void addDependingOnInformation(Insert<T> insert, Map<String, Object> additionalColumnValues) {

DbAction dependingOn = insert.getDependingOn();

if (dependingOn != null) {
if (dependingOn == null) {
return;
}

JdbcPersistentEntity<?> persistentEntity = context.getRequiredPersistentEntity(dependingOn.getEntityType());
String columnName = persistentEntity.getTableName();
Object entity = dependingOn.getEntity();
Object identifier = persistentEntity.getIdentifierAccessor(entity).getIdentifier();
JdbcPersistentEntity<?> persistentEntity = context.getRequiredPersistentEntity(dependingOn.getEntityType());

additionalColumnValues.put(columnName, identifier);
}
String columnName = getColumnNameForReverseColumn(insert, persistentEntity);

Object identifier = getIdFromEntityDependingOn(dependingOn, persistentEntity);

additionalColumnValues.put(columnName, identifier);
}

private Object getIdFromEntityDependingOn(DbAction dependingOn, JdbcPersistentEntity<?> persistentEntity) {
return persistentEntity.getIdentifierAccessor(dependingOn.getEntity()).getIdentifier();
}

private <T> String getColumnNameForReverseColumn(Insert<T> insert, JdbcPersistentEntity<?> persistentEntity) {

PropertyPath path = insert.getPropertyPath().getPath();

Assert.notNull(path, "There shouldn't be an insert depending on another insert without having a PropertyPath.");

return persistentEntity.getRequiredPersistentProperty(path.getSegment()).getReverseColumnName();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import org.springframework.data.jdbc.mapping.model.JdbcMappingContext;
import org.springframework.data.jdbc.mapping.model.JdbcPersistentEntity;
import org.springframework.data.jdbc.mapping.model.JdbcPersistentProperty;
import org.springframework.data.jdbc.mapping.model.PropertyPaths;
import org.springframework.data.jdbc.repository.SimpleJdbcRepository;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.PropertyPath;
Expand Down Expand Up @@ -267,7 +266,7 @@ String createDeleteAllSql(PropertyPath path) {
return String.format("DELETE FROM %s", entity.getTableName());
}

JdbcPersistentEntity<?> entityToDelete = context.getRequiredPersistentEntity(PropertyPaths.getLeafType(path));
JdbcPersistentEntity<?> entityToDelete = context.getRequiredPersistentEntity(path.getLeafType());

JdbcPersistentEntity<?> owningEntity = context.getRequiredPersistentEntity(path.getOwningType());
JdbcPersistentProperty property = owningEntity.getRequiredPersistentProperty(path.getSegment());
Expand All @@ -285,7 +284,7 @@ private String createDeleteByListSql() {

String createDeleteByPath(PropertyPath path) {

JdbcPersistentEntity<?> entityToDelete = context.getRequiredPersistentEntity(PropertyPaths.getLeafType(path));
JdbcPersistentEntity<?> entityToDelete = context.getRequiredPersistentEntity(path.getLeafType());
JdbcPersistentEntity<?> owningEntity = context.getRequiredPersistentEntity(path.getOwningType());
JdbcPersistentProperty property = owningEntity.getRequiredPersistentProperty(path.getSegment());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import java.util.HashMap;
import java.util.Map;

import org.springframework.data.mapping.PropertyPath;
import org.springframework.util.Assert;

/**
Expand All @@ -43,6 +42,11 @@ public abstract class DbAction<T> {
*/
private final T entity;

/**
* The path from the Aggregate Root to the entity affected by this {@link DbAction}.
*/
private final JdbcPropertyPath propertyPath;

/**
* Key-value-pairs to specify additional values to be used with the statement which can't be obtained from the entity,
* nor from {@link DbAction}s {@literal this} depends on. A used case are map keys, which need to be persisted with
Expand All @@ -57,27 +61,28 @@ public abstract class DbAction<T> {
*/
private final DbAction dependingOn;

private DbAction(Class<T> entityType, T entity, DbAction dependingOn) {
private DbAction(Class<T> entityType, T entity, JdbcPropertyPath propertyPath, DbAction dependingOn) {

this.entityType = entityType;
this.entity = entity;
this.propertyPath = propertyPath;
this.dependingOn = dependingOn;
}

public static <T> Insert<T> insert(T entity, DbAction dependingOn) {
return new Insert<>(entity, dependingOn);
public static <T> Insert<T> insert(T entity, JdbcPropertyPath propertyPath, DbAction dependingOn) {
return new Insert<>(entity, propertyPath, dependingOn);
}

public static <T> Update<T> update(T entity, DbAction dependingOn) {
return new Update<>(entity, dependingOn);
public static <T> Update<T> update(T entity, JdbcPropertyPath propertyPath, DbAction dependingOn) {
return new Update<>(entity, propertyPath, dependingOn);
}

public static <T> Delete<T> delete(Object id, Class<T> type, T entity, PropertyPath propertyPath,
public static <T> Delete<T> delete(Object id, Class<T> type, T entity, JdbcPropertyPath propertyPath,
DbAction dependingOn) {
return new Delete<>(id, type, entity, propertyPath, dependingOn);
}

public static <T> DeleteAll<T> deleteAll(Class<T> type, PropertyPath propertyPath, DbAction dependingOn) {
public static <T> DeleteAll<T> deleteAll(Class<T> type, JdbcPropertyPath propertyPath, DbAction dependingOn) {
return new DeleteAll<>(type, propertyPath, dependingOn);
}

Expand All @@ -90,8 +95,9 @@ public static <T> DeleteAll<T> deleteAll(Class<T> type, PropertyPath propertyPat
*/
abstract static class InsertOrUpdate<T> extends DbAction<T> {

InsertOrUpdate(T entity, DbAction dependingOn) {
super((Class<T>) entity.getClass(), entity, dependingOn);
@SuppressWarnings("unchecked")
InsertOrUpdate(T entity, JdbcPropertyPath propertyPath, DbAction dependingOn) {
super((Class<T>) entity.getClass(), entity, propertyPath, dependingOn);
}
}

Expand All @@ -102,8 +108,8 @@ abstract static class InsertOrUpdate<T> extends DbAction<T> {
*/
public static class Insert<T> extends InsertOrUpdate<T> {

private Insert(T entity, DbAction dependingOn) {
super(entity, dependingOn);
private Insert(T entity, JdbcPropertyPath propertyPath, DbAction dependingOn) {
super(entity, propertyPath, dependingOn);
}

@Override
Expand All @@ -119,8 +125,8 @@ void executeWith(Interpreter interpreter) {
*/
public static class Update<T> extends InsertOrUpdate<T> {

private Update(T entity, DbAction dependingOn) {
super(entity, dependingOn);
private Update(T entity, JdbcPropertyPath propertyPath, DbAction dependingOn) {
super(entity, propertyPath, dependingOn);
}

@Override
Expand All @@ -143,20 +149,13 @@ public static class Delete<T> extends DbAction<T> {
*/
private final Object rootId;

/**
* {@link PropertyPath} which connects the aggregate root with the entities to be deleted. If this is the action to
* delete the root enity itself, this is {@literal null}.
*/
private final PropertyPath propertyPath;

private Delete(Object rootId, Class<T> type, T entity, PropertyPath propertyPath, DbAction dependingOn) {
private Delete(Object rootId, Class<T> type, T entity, JdbcPropertyPath propertyPath, DbAction dependingOn) {

super(type, entity, dependingOn);
super(type, entity, propertyPath, dependingOn);

Assert.notNull(rootId, "rootId must not be null.");

this.rootId = rootId;
this.propertyPath = propertyPath;
}

@Override
Expand All @@ -170,19 +169,10 @@ void executeWith(Interpreter interpreter) {
*
* @param <T> type o the entity for which this represents a database interaction
*/
@Getter
public static class DeleteAll<T> extends DbAction<T> {

/**
*
*/
private final PropertyPath propertyPath;

private DeleteAll(Class<T> entityType, PropertyPath propertyPath, DbAction dependingOn) {

super(entityType, null, dependingOn);

this.propertyPath = propertyPath;
private DeleteAll(Class<T> entityType, JdbcPropertyPath propertyPath, DbAction dependingOn) {
super(entityType, null, propertyPath, dependingOn);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package org.springframework.data.jdbc.core.conversion;

import org.springframework.data.jdbc.mapping.model.JdbcMappingContext;
import org.springframework.data.jdbc.mapping.model.PropertyPaths;

/**
* Converts an entity that is about to be deleted into {@link DbAction}s inside a {@link AggregateChange} that need to be
Expand All @@ -43,7 +42,7 @@ public void write(Object id, AggregateChange aggregateChange) {
private void deleteAll(AggregateChange aggregateChange) {

context.referencedEntities(aggregateChange.getEntityType(), null)
.forEach(p -> aggregateChange.addAction(DbAction.deleteAll(PropertyPaths.getLeafType(p), p, null)));
.forEach(p -> aggregateChange.addAction(DbAction.deleteAll(p.getLeafType(), new JdbcPropertyPath(p), null)));

aggregateChange.addAction(DbAction.deleteAll(aggregateChange.getEntityType(), null, null));
}
Expand All @@ -54,5 +53,4 @@ private void deleteById(Object id, AggregateChange aggregateChange) {

aggregateChange.addAction(DbAction.delete(id, aggregateChange.getEntityType(), aggregateChange.getEntity(), null, null));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -52,76 +52,85 @@ public void write(Object o, AggregateChange aggregateChange) {

private void write(Object o, AggregateChange aggregateChange, DbAction dependingOn) {

JdbcPersistentEntityInformation<Object, ?> entityInformation = context
.getRequiredPersistentEntityInformation((Class<Object>) o.getClass());
Class<Object> type = (Class<Object>) o.getClass();
JdbcPersistentEntityInformation<Object, ?> entityInformation = context.getRequiredPersistentEntityInformation(type);
JdbcPropertyPath propertyPath = JdbcPropertyPath.from("", type);

if (entityInformation.isNew(o)) {

Insert<Object> insert = DbAction.insert(o, dependingOn);
Insert<Object> insert = DbAction.insert(o, propertyPath, dependingOn);
aggregateChange.addAction(insert);

referencedEntities(o).forEach(propertyAndValue -> saveReferencedEntities(propertyAndValue, aggregateChange, insert));
referencedEntities(o).forEach(propertyAndValue -> saveReferencedEntities(propertyAndValue, aggregateChange,
propertyPath.nested(propertyAndValue.property.getName()), insert));
} else {

deleteReferencedEntities(entityInformation.getRequiredId(o), aggregateChange);

Update<Object> update = DbAction.update(o, dependingOn);
Update<Object> update = DbAction.update(o, propertyPath, dependingOn);
aggregateChange.addAction(update);

referencedEntities(o).forEach(propertyAndValue -> insertReferencedEntities(propertyAndValue, aggregateChange, update));
referencedEntities(o).forEach(
propertyAndValue -> insertReferencedEntities(propertyAndValue, aggregateChange, propertyPath.nested(propertyAndValue.property.getName()), update));
}
}

private void saveReferencedEntities(PropertyAndValue propertyAndValue, AggregateChange aggregateChange, DbAction dependingOn) {
private void saveReferencedEntities(PropertyAndValue propertyAndValue, AggregateChange aggregateChange,
JdbcPropertyPath propertyPath, DbAction dependingOn) {

saveActions(propertyAndValue, dependingOn).forEach(a -> {
saveActions(propertyAndValue, propertyPath, dependingOn).forEach(a -> {

aggregateChange.addAction(a);
referencedEntities(propertyAndValue.value).forEach(pav -> saveReferencedEntities(pav, aggregateChange, a));
referencedEntities(propertyAndValue.value)
.forEach(pav -> saveReferencedEntities(pav, aggregateChange, propertyPath.nested(pav.property.getName()), a));
});
}

private Stream<DbAction> saveActions(PropertyAndValue propertyAndValue, DbAction dependingOn) {
private Stream<DbAction> saveActions(PropertyAndValue propertyAndValue, JdbcPropertyPath propertyPath,
DbAction dependingOn) {

if (Map.Entry.class.isAssignableFrom(ClassUtils.getUserClass(propertyAndValue.value))) {
return mapEntrySaveAction(propertyAndValue, dependingOn);
return mapEntrySaveAction(propertyAndValue, propertyPath, dependingOn);
}

return Stream.of(singleSaveAction(propertyAndValue.value, dependingOn));
return Stream.of(singleSaveAction(propertyAndValue.value, propertyPath, dependingOn));
}

private Stream<DbAction> mapEntrySaveAction(PropertyAndValue propertyAndValue, DbAction dependingOn) {
private Stream<DbAction> mapEntrySaveAction(PropertyAndValue propertyAndValue, JdbcPropertyPath propertyPath,
DbAction dependingOn) {

Map.Entry<Object, Object> entry = (Map.Entry) propertyAndValue.value;

DbAction action = singleSaveAction(entry.getValue(), dependingOn);
DbAction action = singleSaveAction(entry.getValue(), propertyPath, dependingOn);
action.getAdditionalValues().put(propertyAndValue.property.getKeyColumn(), entry.getKey());
return Stream.of(action);
}

private <T> DbAction singleSaveAction(T t, DbAction dependingOn) {
private <T> DbAction singleSaveAction(T t, JdbcPropertyPath propertyPath, DbAction dependingOn) {

JdbcPersistentEntityInformation<T, ?> entityInformation = context
.getRequiredPersistentEntityInformation((Class<T>) ClassUtils.getUserClass(t));

return entityInformation.isNew(t) ? DbAction.insert(t, dependingOn) : DbAction.update(t, dependingOn);
return entityInformation.isNew(t) ? DbAction.insert(t, propertyPath, dependingOn)
: DbAction.update(t, propertyPath, dependingOn);
}

private void insertReferencedEntities(PropertyAndValue propertyAndValue, AggregateChange aggregateChange, DbAction dependingOn) {
private void insertReferencedEntities(PropertyAndValue propertyAndValue, AggregateChange aggregateChange,
JdbcPropertyPath propertyPath, DbAction dependingOn) {

Insert<Object> insert;
if (propertyAndValue.property.isQualified()) {

Entry<Object, Object> valueAsEntry = (Entry<Object, Object>) propertyAndValue.value;
insert = DbAction.insert(valueAsEntry.getValue(), dependingOn);
insert = DbAction.insert(valueAsEntry.getValue(), propertyPath, dependingOn);
insert.getAdditionalValues().put(propertyAndValue.property.getKeyColumn(), valueAsEntry.getKey());
} else {
insert = DbAction.insert(propertyAndValue.value, dependingOn);
insert = DbAction.insert(propertyAndValue.value, propertyPath, dependingOn);
}

aggregateChange.addAction(insert);
referencedEntities(insert.getEntity())
.forEach(pav -> insertReferencedEntities(pav, aggregateChange, dependingOn));
.forEach(pav -> insertReferencedEntities(pav, aggregateChange, propertyPath.nested(pav.property.getName()), dependingOn));
}

private Stream<PropertyAndValue> referencedEntities(Object o) {
Expand All @@ -133,7 +142,7 @@ private Stream<PropertyAndValue> referencedEntities(Object o) {
.flatMap( //
p -> referencedEntity(p, persistentEntity.getPropertyAccessor(o)) //
.map(e -> new PropertyAndValue(p, e)) //
);
);
}

private Stream<Object> referencedEntity(JdbcPersistentProperty p, PersistentPropertyAccessor propertyAccessor) {
Expand Down
Loading