Skip to content

Commit 55cc846

Browse files
committed
DATAJDBC-227 - Refactored JdbcEntityWriter towards a cleaner structure which better allows implementation of new features.
Migrated Actions from JdbcPropertyPath ot PersistentPropertyPath. Split DbAction in interface and implementation. extracted interfaces WithDependingOn and WithPropertyPath extracted interfaces WithEntity extracted separated InsertRoot split Update and UpdateRoot
1 parent 31f3f2f commit 55cc846

32 files changed

+1086
-566
lines changed

src/main/java/org/springframework/data/jdbc/core/CascadingDataAccessStrategy.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import java.util.function.Consumer;
2222
import java.util.function.Function;
2323

24-
import org.springframework.data.mapping.PropertyPath;
24+
import org.springframework.data.mapping.PersistentPropertyPath;
2525
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
2626

2727
/**
@@ -45,8 +45,8 @@ public <T> void insert(T instance, Class<T> domainType, Map<String, Object> addi
4545
}
4646

4747
@Override
48-
public <S> void update(S instance, Class<S> domainType) {
49-
collectVoid(das -> das.update(instance, domainType));
48+
public <S> boolean update(S instance, Class<S> domainType) {
49+
return collect(das -> das.update(instance, domainType));
5050
}
5151

5252
@Override
@@ -55,7 +55,7 @@ public void delete(Object id, Class<?> domainType) {
5555
}
5656

5757
@Override
58-
public void delete(Object rootId, PropertyPath propertyPath) {
58+
public void delete(Object rootId, PersistentPropertyPath<RelationalPersistentProperty> propertyPath) {
5959
collectVoid(das -> das.delete(rootId, propertyPath));
6060
}
6161

@@ -65,7 +65,7 @@ public <T> void deleteAll(Class<T> domainType) {
6565
}
6666

6767
@Override
68-
public void deleteAll(PropertyPath propertyPath) {
68+
public void deleteAll(PersistentPropertyPath<RelationalPersistentProperty> propertyPath) {
6969
collectVoid(das -> das.deleteAll(propertyPath));
7070
}
7171

src/main/java/org/springframework/data/jdbc/core/DataAccessStrategy.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.util.Map;
1919

20+
import org.springframework.data.mapping.PersistentPropertyPath;
2021
import org.springframework.data.mapping.PropertyPath;
2122
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
2223
import org.springframework.lang.Nullable;
@@ -48,8 +49,9 @@ public interface DataAccessStrategy {
4849
* @param instance the instance to save. Must not be {@code null}.
4950
* @param domainType the type of the instance to save. Must not be {@code null}.
5051
* @param <T> the type of the instance to save.
52+
* @return wether the update actually updated a row.
5153
*/
52-
<T> void update(T instance, Class<T> domainType);
54+
<T> boolean update(T instance, Class<T> domainType);
5355

5456
/**
5557
* deletes a single row identified by the id, from the table identified by the domainType. Does not handle cascading
@@ -63,11 +65,10 @@ public interface DataAccessStrategy {
6365

6466
/**
6567
* Deletes all entities reachable via {@literal propertyPath} from the instance identified by {@literal rootId}.
66-
*
67-
* @param rootId Id of the root object on which the {@literal propertyPath} is based. Must not be {@code null}.
68+
* @param rootId Id of the root object on which the {@literal propertyPath} is based. Must not be {@code null}.
6869
* @param propertyPath Leading from the root object to the entities to be deleted. Must not be {@code null}.
6970
*/
70-
void delete(Object rootId, PropertyPath propertyPath);
71+
void delete(Object rootId, PersistentPropertyPath<RelationalPersistentProperty> propertyPath);
7172

7273
/**
7374
* Deletes all entities of the given domain type.
@@ -82,7 +83,7 @@ public interface DataAccessStrategy {
8283
*
8384
* @param propertyPath Leading from the root object to the entities to be deleted. Must not be {@code null}.
8485
*/
85-
void deleteAll(PropertyPath propertyPath);
86+
void deleteAll(PersistentPropertyPath<RelationalPersistentProperty> propertyPath);
8687

8788
/**
8889
* Counts the rows in the table representing the given domain type.

src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
import org.springframework.data.convert.EntityInstantiators;
3131
import org.springframework.data.jdbc.support.JdbcUtil;
3232
import org.springframework.data.mapping.PersistentPropertyAccessor;
33+
import org.springframework.data.mapping.PersistentPropertyPath;
3334
import org.springframework.data.mapping.PropertyHandler;
34-
import org.springframework.data.mapping.PropertyPath;
3535
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
3636
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
3737
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
@@ -118,11 +118,11 @@ public <T> void insert(T instance, Class<T> domainType, Map<String, Object> addi
118118
* @see org.springframework.data.jdbc.core.DataAccessStrategy#update(java.lang.Object, java.lang.Class)
119119
*/
120120
@Override
121-
public <S> void update(S instance, Class<S> domainType) {
121+
public <S> boolean update(S instance, Class<S> domainType) {
122122

123123
RelationalPersistentEntity<S> persistentEntity = getRequiredPersistentEntity(domainType);
124124

125-
operations.update(sql(domainType).getUpdate(), getPropertyMap(instance, persistentEntity));
125+
return operations.update(sql(domainType).getUpdate(), getPropertyMap(instance, persistentEntity)) != 0;
126126
}
127127

128128
/*
@@ -143,11 +143,12 @@ public void delete(Object id, Class<?> domainType) {
143143
* @see org.springframework.data.jdbc.core.DataAccessStrategy#delete(java.lang.Object, org.springframework.data.mapping.PropertyPath)
144144
*/
145145
@Override
146-
public void delete(Object rootId, PropertyPath propertyPath) {
146+
public void delete(Object rootId, PersistentPropertyPath<RelationalPersistentProperty> propertyPath) {
147147

148-
RelationalPersistentEntity<?> rootEntity = context.getRequiredPersistentEntity(propertyPath.getOwningType());
148+
RelationalPersistentEntity<?> rootEntity = context
149+
.getRequiredPersistentEntity(propertyPath.getBaseProperty().getOwner().getType());
149150

150-
RelationalPersistentProperty referencingProperty = rootEntity.getRequiredPersistentProperty(propertyPath.getSegment());
151+
RelationalPersistentProperty referencingProperty = propertyPath.getLeafProperty();
151152
Assert.notNull(referencingProperty, "No property found matching the PropertyPath " + propertyPath);
152153

153154
String format = sql(rootEntity.getType()).createDeleteByPath(propertyPath);
@@ -171,8 +172,9 @@ public <T> void deleteAll(Class<T> domainType) {
171172
* @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteAll(org.springframework.data.mapping.PropertyPath)
172173
*/
173174
@Override
174-
public void deleteAll(PropertyPath propertyPath) {
175-
operations.getJdbcOperations().update(sql(propertyPath.getOwningType().getType()).createDeleteAllSql(propertyPath));
175+
public void deleteAll(PersistentPropertyPath<RelationalPersistentProperty> propertyPath) {
176+
operations.getJdbcOperations()
177+
.update(sql(propertyPath.getBaseProperty().getOwner().getType()).createDeleteAllSql(propertyPath));
176178
}
177179

178180
/*
@@ -339,7 +341,10 @@ private <S> Optional<Object> getIdFromHolder(KeyHolder holder, RelationalPersist
339341
} catch (InvalidDataAccessApiUsageException e) {
340342
// Postgres returns a value for each column
341343
Map<String, Object> keys = holder.getKeys();
342-
return Optional.ofNullable(keys == null ? null : keys.get(persistentEntity.getIdColumn()));
344+
return Optional.ofNullable( //
345+
keys == null || persistentEntity.getIdProperty() == null //
346+
? null //
347+
: keys.get(persistentEntity.getIdColumn()));
343348
}
344349
}
345350

src/main/java/org/springframework/data/jdbc/core/DefaultJdbcInterpreter.java

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,22 @@
1818
import java.util.HashMap;
1919
import java.util.Map;
2020

21-
import org.springframework.data.mapping.PropertyPath;
21+
import org.springframework.data.mapping.PersistentPropertyPath;
22+
import org.springframework.data.relational.core.conversion.AbstractDbAction.Delete;
23+
import org.springframework.data.relational.core.conversion.AbstractDbAction.DeleteAll;
24+
import org.springframework.data.relational.core.conversion.AbstractDbAction.Insert;
25+
import org.springframework.data.relational.core.conversion.AbstractDbAction.InsertRoot;
26+
import org.springframework.data.relational.core.conversion.AbstractDbAction.Merge;
27+
import org.springframework.data.relational.core.conversion.AbstractDbAction.Update;
28+
import org.springframework.data.relational.core.conversion.AbstractDbAction.UpdateRoot;
2229
import org.springframework.data.relational.core.conversion.DbAction;
2330
import org.springframework.data.relational.core.conversion.Interpreter;
24-
import org.springframework.data.relational.core.conversion.DbAction.Delete;
25-
import org.springframework.data.relational.core.conversion.DbAction.DeleteAll;
26-
import org.springframework.data.relational.core.conversion.DbAction.Insert;
27-
import org.springframework.data.relational.core.conversion.DbAction.Update;
31+
import org.springframework.data.relational.core.conversion.WithDependingOn;
32+
import org.springframework.data.relational.core.conversion.WithEntity;
33+
import org.springframework.data.relational.core.conversion.WithPropertyPath;
2834
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
2935
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
36+
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
3037
import org.springframework.lang.Nullable;
3138
import org.springframework.util.Assert;
3239

@@ -53,68 +60,82 @@ public <T> void interpret(Insert<T> insert) {
5360
accessStrategy.insert(insert.getEntity(), insert.getEntityType(), createAdditionalColumnValues(insert));
5461
}
5562

63+
@Override
64+
public <T> void interpret(InsertRoot<T> insert) {
65+
accessStrategy.insert(insert.getEntity(), insert.getEntityType(), new HashMap<>());
66+
}
67+
5668
@Override
5769
public <T> void interpret(Update<T> update) {
5870
accessStrategy.update(update.getEntity(), update.getEntityType());
5971
}
6072

73+
public <T> void interpret(UpdateRoot<T> update) {
74+
accessStrategy.update(update.getEntity(), update.getEntityType());
75+
}
76+
77+
@Override
78+
public <T> void interpret(Merge<T> merge) {
79+
80+
// dummy implementation
81+
if (!accessStrategy.update(merge.getEntity(), merge.getEntityType())) {
82+
accessStrategy.insert(merge.getEntity(), merge.getEntityType(), createAdditionalColumnValues(merge));
83+
}
84+
}
85+
6186
@Override
6287
public <T> void interpret(Delete<T> delete) {
6388

6489
if (delete.getPropertyPath() == null) {
6590
accessStrategy.delete(delete.getRootId(), delete.getEntityType());
6691
} else {
67-
accessStrategy.delete(delete.getRootId(), delete.getPropertyPath().getPath());
92+
accessStrategy.delete(delete.getRootId(), delete.getPropertyPath());
6893
}
6994
}
7095

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

7499
if (delete.getEntityType() == null) {
75-
accessStrategy.deleteAll(delete.getPropertyPath().getPath());
100+
accessStrategy.deleteAll(delete.getPropertyPath());
76101
} else {
77102
accessStrategy.deleteAll(delete.getEntityType());
78103
}
79104
}
80105

81-
private <T> Map<String, Object> createAdditionalColumnValues(Insert<T> insert) {
106+
private <T> Map<String, Object> createAdditionalColumnValues(WithDependingOn<T> action) {
82107

83108
Map<String, Object> additionalColumnValues = new HashMap<>();
84-
addDependingOnInformation(insert, additionalColumnValues);
85-
additionalColumnValues.putAll(insert.getAdditionalValues());
109+
addDependingOnInformation((WithDependingOn<? extends Object>) action, additionalColumnValues);
110+
additionalColumnValues.putAll(action.getAdditionalValues());
86111

87112
return additionalColumnValues;
88113
}
89114

90-
private <T> void addDependingOnInformation(Insert<T> insert, Map<String, Object> additionalColumnValues) {
91-
92-
DbAction dependingOn = insert.getDependingOn();
115+
private <T> void addDependingOnInformation(WithDependingOn<T> action, Map<String, Object> additionalColumnValues) {
93116

94-
if (dependingOn == null) {
95-
return;
96-
}
117+
WithEntity<?> dependingOn = action.getDependingOn();
97118

98119
RelationalPersistentEntity<?> persistentEntity = context.getRequiredPersistentEntity(dependingOn.getEntityType());
99120

100-
String columnName = getColumnNameForReverseColumn(insert, persistentEntity);
121+
String columnName = getColumnNameForReverseColumn(action);
101122

102123
Object identifier = getIdFromEntityDependingOn(dependingOn, persistentEntity);
103124

104125
additionalColumnValues.put(columnName, identifier);
105126
}
106127

107128
@Nullable
108-
private Object getIdFromEntityDependingOn(DbAction dependingOn, RelationalPersistentEntity<?> persistentEntity) {
129+
private Object getIdFromEntityDependingOn(WithEntity<?> dependingOn, RelationalPersistentEntity<?> persistentEntity) {
109130
return persistentEntity.getIdentifierAccessor(dependingOn.getEntity()).getIdentifier();
110131
}
111132

112-
private <T> String getColumnNameForReverseColumn(Insert<T> insert, RelationalPersistentEntity<?> persistentEntity) {
133+
private String getColumnNameForReverseColumn(WithPropertyPath<?> action) {
113134

114-
PropertyPath path = insert.getPropertyPath().getPath();
135+
PersistentPropertyPath<RelationalPersistentProperty> path = action.getPropertyPath();
115136

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

118-
return persistentEntity.getRequiredPersistentProperty(path.getSegment()).getReverseColumnName();
139+
return path.getLeafProperty().getReverseColumnName();
119140
}
120141
}

src/main/java/org/springframework/data/jdbc/core/DelegatingDataAccessStrategy.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.util.Map;
1919

20+
import org.springframework.data.mapping.PersistentPropertyPath;
2021
import org.springframework.data.mapping.PropertyPath;
2122
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
2223
import org.springframework.util.Assert;
@@ -38,12 +39,12 @@ public <T> void insert(T instance, Class<T> domainType, Map<String, Object> addi
3839
}
3940

4041
@Override
41-
public <S> void update(S instance, Class<S> domainType) {
42-
delegate.update(instance, domainType);
42+
public <S> boolean update(S instance, Class<S> domainType) {
43+
return delegate.update(instance, domainType);
4344
}
4445

4546
@Override
46-
public void delete(Object rootId, PropertyPath propertyPath) {
47+
public void delete(Object rootId, PersistentPropertyPath<RelationalPersistentProperty> propertyPath) {
4748
delegate.delete(rootId, propertyPath);
4849
}
4950

@@ -58,7 +59,7 @@ public <T> void deleteAll(Class<T> domainType) {
5859
}
5960

6061
@Override
61-
public void deleteAll(PropertyPath propertyPath) {
62+
public void deleteAll(PersistentPropertyPath<RelationalPersistentProperty> propertyPath) {
6263
delegate.deleteAll(propertyPath);
6364
}
6465

0 commit comments

Comments
 (0)