17
17
18
18
import lombok .RequiredArgsConstructor ;
19
19
20
- import java .util .Collections ;
21
20
import java .util .Map ;
22
21
23
22
import org .springframework .dao .IncorrectUpdateSemanticsDataAccessException ;
34
33
import org .springframework .data .relational .core .conversion .DbAction .Update ;
35
34
import org .springframework .data .relational .core .conversion .DbAction .UpdateRoot ;
36
35
import org .springframework .data .relational .core .conversion .Interpreter ;
36
+ import org .springframework .data .relational .core .conversion .RelationalConverter ;
37
+ import org .springframework .data .relational .core .conversion .RelationalEntityVersionUtils ;
37
38
import org .springframework .data .relational .core .mapping .PersistentPropertyPathExtension ;
38
39
import org .springframework .data .relational .core .mapping .RelationalMappingContext ;
39
40
import org .springframework .data .relational .core .mapping .RelationalPersistentEntity ;
48
49
* @author Jens Schauder
49
50
* @author Mark Paluch
50
51
* @author Myeonghyeon Lee
52
+ * @author Tyler Van Gorder
51
53
*/
52
54
@ RequiredArgsConstructor
53
55
class DefaultJdbcInterpreter implements Interpreter {
54
56
55
57
public static final String UPDATE_FAILED = "Failed to update entity [%s]. Id [%s] not found in database." ;
58
+ private final RelationalConverter converter ;
56
59
private final RelationalMappingContext context ;
57
60
private final DataAccessStrategy accessStrategy ;
58
61
@@ -62,21 +65,40 @@ class DefaultJdbcInterpreter implements Interpreter {
62
65
*/
63
66
@ Override
64
67
public <T > void interpret (Insert <T > insert ) {
65
-
66
68
Object id = accessStrategy .insert (insert .getEntity (), insert .getEntityType (), getParentKeys (insert ));
67
-
68
69
insert .setGeneratedId (id );
69
70
}
70
71
72
+ @ SuppressWarnings ("unchecked" )
73
+ private <T > RelationalPersistentEntity <T > getRequiredPersistentEntity (Class <T > type ) {
74
+ return (RelationalPersistentEntity <T >) context .getRequiredPersistentEntity (type );
75
+ }
76
+
71
77
/*
72
78
* (non-Javadoc)
73
79
* @see org.springframework.data.relational.core.conversion.Interpreter#interpret(org.springframework.data.relational.core.conversion.DbAction.InsertRoot)
74
80
*/
75
81
@ Override
76
82
public <T > void interpret (InsertRoot <T > insert ) {
77
83
78
- Object id = accessStrategy .insert (insert .getEntity (), insert .getEntityType (), Collections .emptyMap ());
79
- insert .setGeneratedId (id );
84
+ RelationalPersistentEntity <T > persistentEntity = getRequiredPersistentEntity (insert .getEntityType ());
85
+
86
+ if (persistentEntity .hasVersionProperty ()) {
87
+ // The interpreter is responsible for setting the initial version on the entity prior to calling insert.
88
+ Number version = RelationalEntityVersionUtils .getVersionNumberFromEntity (insert .getEntity (), persistentEntity ,
89
+ converter );
90
+ if (version != null && version .longValue () > 0 ) {
91
+ throw new IllegalArgumentException ("The entity cannot be inserted because it already has a version." );
92
+ }
93
+ T rootEntity = RelationalEntityVersionUtils .setVersionNumberOnEntity (insert .getEntity (), 1 , persistentEntity ,
94
+ converter );
95
+ Object id = accessStrategy .insert (rootEntity , insert .getEntityType (), Identifier .empty ());
96
+ insert .setNextVersion (1 );
97
+ insert .setGeneratedId (id );
98
+ } else {
99
+ Object id = accessStrategy .insert (insert .getEntity (), insert .getEntityType (), Identifier .empty ());
100
+ insert .setGeneratedId (id );
101
+ }
80
102
}
81
103
82
104
/*
@@ -100,10 +122,31 @@ public <T> void interpret(Update<T> update) {
100
122
@ Override
101
123
public <T > void interpret (UpdateRoot <T > update ) {
102
124
103
- if (!accessStrategy .update (update .getEntity (), update .getEntityType ())) {
104
-
105
- throw new IncorrectUpdateSemanticsDataAccessException (
106
- String .format (UPDATE_FAILED , update .getEntity (), getIdFrom (update )));
125
+ RelationalPersistentEntity <T > persistentEntity = getRequiredPersistentEntity (update .getEntityType ());
126
+
127
+ if (persistentEntity .hasVersionProperty ()) {
128
+ // If the root aggregate has a version property, increment it.
129
+ Number previousVersion = RelationalEntityVersionUtils .getVersionNumberFromEntity (update .getEntity (),
130
+ persistentEntity , converter );
131
+ Assert .notNull (previousVersion , "The root aggregate cannot be updated because the version property is null." );
132
+
133
+ T rootEntity = RelationalEntityVersionUtils .setVersionNumberOnEntity (update .getEntity (),
134
+ previousVersion .longValue () + 1 , persistentEntity ,
135
+ converter );
136
+
137
+ if (accessStrategy .updateWithVersion (rootEntity , update .getEntityType (), previousVersion )) {
138
+ // Successful update, set the in-memory version on the action.
139
+ update .setNextVersion (previousVersion );
140
+ } else {
141
+ throw new IncorrectUpdateSemanticsDataAccessException (
142
+ String .format (UPDATE_FAILED , update .getEntity (), getIdFrom (update )));
143
+ }
144
+ } else {
145
+ if (!accessStrategy .update (update .getEntity (), update .getEntityType ())) {
146
+
147
+ throw new IncorrectUpdateSemanticsDataAccessException (
148
+ String .format (UPDATE_FAILED , update .getEntity (), getIdFrom (update )));
149
+ }
107
150
}
108
151
}
109
152
@@ -135,7 +178,16 @@ public <T> void interpret(Delete<T> delete) {
135
178
*/
136
179
@ Override
137
180
public <T > void interpret (DeleteRoot <T > delete ) {
138
- accessStrategy .delete (delete .getRootId (), delete .getEntityType ());
181
+
182
+ if (delete .getEntity () != null ) {
183
+ RelationalPersistentEntity <T > persistentEntity = getRequiredPersistentEntity (delete .getEntityType ());
184
+ if (persistentEntity .hasVersionProperty ()) {
185
+ accessStrategy .deleteWithVersion (delete .getEntity (), delete .getEntityType ());
186
+ return ;
187
+ }
188
+ }
189
+
190
+ accessStrategy .delete (delete .getId (), delete .getEntityType ());
139
191
}
140
192
141
193
/*
@@ -177,13 +229,13 @@ private Object getParentId(DbAction.WithDependingOn<?> action) {
177
229
PersistentPropertyPathExtension path = new PersistentPropertyPathExtension (context , action .getPropertyPath ());
178
230
PersistentPropertyPathExtension idPath = path .getIdDefiningParentPath ();
179
231
180
- DbAction .WithEntity idOwningAction = getIdOwningAction (action , idPath );
232
+ DbAction .WithEntity <?> idOwningAction = getIdOwningAction (action , idPath );
181
233
182
234
return getIdFrom (idOwningAction );
183
235
}
184
236
185
- @ SuppressWarnings ( "unchecked" )
186
- private DbAction . WithEntity getIdOwningAction ( DbAction . WithEntity action , PersistentPropertyPathExtension idPath ) {
237
+ private DbAction . WithEntity <?> getIdOwningAction ( DbAction . WithEntity <?> action ,
238
+ PersistentPropertyPathExtension idPath ) {
187
239
188
240
if (!(action instanceof DbAction .WithDependingOn )) {
189
241
@@ -193,7 +245,7 @@ private DbAction.WithEntity getIdOwningAction(DbAction.WithEntity action, Persis
193
245
return action ;
194
246
}
195
247
196
- DbAction .WithDependingOn withDependingOn = (DbAction .WithDependingOn ) action ;
248
+ DbAction .WithDependingOn <?> withDependingOn = (DbAction .WithDependingOn <?> ) action ;
197
249
198
250
if (idPath .matches (withDependingOn .getPropertyPath ())) {
199
251
return action ;
@@ -202,7 +254,7 @@ private DbAction.WithEntity getIdOwningAction(DbAction.WithEntity action, Persis
202
254
return getIdOwningAction (withDependingOn .getDependingOn (), idPath );
203
255
}
204
256
205
- private Object getIdFrom (DbAction .WithEntity idOwningAction ) {
257
+ private Object getIdFrom (DbAction .WithEntity <?> idOwningAction ) {
206
258
207
259
if (idOwningAction instanceof DbAction .WithGeneratedId ) {
208
260
@@ -221,4 +273,5 @@ private Object getIdFrom(DbAction.WithEntity idOwningAction) {
221
273
222
274
return identifier ;
223
275
}
276
+
224
277
}
0 commit comments