20
20
import java .util .Map ;
21
21
22
22
import org .springframework .dao .IncorrectUpdateSemanticsDataAccessException ;
23
+ import org .springframework .dao .OptimisticLockingFailureException ;
23
24
import org .springframework .data .jdbc .core .convert .DataAccessStrategy ;
24
25
import org .springframework .data .mapping .PersistentPropertyPath ;
25
26
import org .springframework .data .relational .core .conversion .DbAction ;
55
56
class DefaultJdbcInterpreter implements Interpreter {
56
57
57
58
public static final String UPDATE_FAILED = "Failed to update entity [%s]. Id [%s] not found in database." ;
59
+ public static final String UPDATE_FAILED_OPTIMISTIC_LOCKING = "Failed to update entity [%s]. The entity was updated since it was rea or it isn't in the database at all." ;
58
60
private final RelationalConverter converter ;
59
61
private final RelationalMappingContext context ;
60
62
private final DataAccessStrategy accessStrategy ;
@@ -65,15 +67,11 @@ class DefaultJdbcInterpreter implements Interpreter {
65
67
*/
66
68
@ Override
67
69
public <T > void interpret (Insert <T > insert ) {
70
+
68
71
Object id = accessStrategy .insert (insert .getEntity (), insert .getEntityType (), getParentKeys (insert ));
69
72
insert .setGeneratedId (id );
70
73
}
71
74
72
- @ SuppressWarnings ("unchecked" )
73
- private <T > RelationalPersistentEntity <T > getRequiredPersistentEntity (Class <T > type ) {
74
- return (RelationalPersistentEntity <T >) context .getRequiredPersistentEntity (type );
75
- }
76
-
77
75
/*
78
76
* (non-Javadoc)
79
77
* @see org.springframework.data.relational.core.conversion.Interpreter#interpret(org.springframework.data.relational.core.conversion.DbAction.InsertRoot)
@@ -83,22 +81,17 @@ public <T> void interpret(InsertRoot<T> insert) {
83
81
84
82
RelationalPersistentEntity <T > persistentEntity = getRequiredPersistentEntity (insert .getEntityType ());
85
83
84
+ Object id ;
86
85
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
- }
86
+
93
87
T rootEntity = RelationalEntityVersionUtils .setVersionNumberOnEntity (insert .getEntity (), 1 , persistentEntity ,
94
88
converter );
95
- Object id = accessStrategy .insert (rootEntity , insert .getEntityType (), Identifier .empty ());
89
+ id = accessStrategy .insert (rootEntity , insert .getEntityType (), Identifier .empty ());
96
90
insert .setNextVersion (1 );
97
- insert .setGeneratedId (id );
98
91
} else {
99
- Object id = accessStrategy .insert (insert .getEntity (), insert .getEntityType (), Identifier .empty ());
100
- insert .setGeneratedId (id );
92
+ id = accessStrategy .insert (insert .getEntity (), insert .getEntityType (), Identifier .empty ());
101
93
}
94
+ insert .setGeneratedId (id );
102
95
}
103
96
104
97
/*
@@ -125,23 +118,25 @@ public <T> void interpret(UpdateRoot<T> update) {
125
118
RelationalPersistentEntity <T > persistentEntity = getRequiredPersistentEntity (update .getEntityType ());
126
119
127
120
if (persistentEntity .hasVersionProperty ()) {
121
+
128
122
// If the root aggregate has a version property, increment it.
129
123
Number previousVersion = RelationalEntityVersionUtils .getVersionNumberFromEntity (update .getEntity (),
130
124
persistentEntity , converter );
125
+
131
126
Assert .notNull (previousVersion , "The root aggregate cannot be updated because the version property is null." );
132
127
133
128
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
- }
129
+ previousVersion .longValue () + 1 , persistentEntity , converter );
130
+
131
+ if (accessStrategy .updateWithVersion (rootEntity , update .getEntityType (), previousVersion )) {
132
+ // Successful update, set the in-memory version on the action.
133
+ update .setNextVersion (previousVersion );
134
+ } else {
135
+ throw new OptimisticLockingFailureException (
136
+ String .format (UPDATE_FAILED_OPTIMISTIC_LOCKING , update .getEntity ()));
137
+ }
144
138
} else {
139
+
145
140
if (!accessStrategy .update (update .getEntity (), update .getEntityType ())) {
146
141
147
142
throw new IncorrectUpdateSemanticsDataAccessException (
@@ -179,10 +174,12 @@ public <T> void interpret(Delete<T> delete) {
179
174
@ Override
180
175
public <T > void interpret (DeleteRoot <T > delete ) {
181
176
182
- if (delete .getEntity () != null ) {
177
+ if (delete .getPreviousVersion () != null ) {
178
+
183
179
RelationalPersistentEntity <T > persistentEntity = getRequiredPersistentEntity (delete .getEntityType ());
184
180
if (persistentEntity .hasVersionProperty ()) {
185
- accessStrategy .deleteWithVersion (delete .getEntity (), delete .getEntityType ());
181
+
182
+ accessStrategy .deleteWithVersion (delete .getId (), delete .getEntityType (), delete .getPreviousVersion ());
186
183
return ;
187
184
}
188
185
}
@@ -274,4 +271,9 @@ private Object getIdFrom(DbAction.WithEntity<?> idOwningAction) {
274
271
return identifier ;
275
272
}
276
273
274
+ @ SuppressWarnings ("unchecked" )
275
+ private <T > RelationalPersistentEntity <T > getRequiredPersistentEntity (Class <T > type ) {
276
+ return (RelationalPersistentEntity <T >) context .getRequiredPersistentEntity (type );
277
+ }
278
+
277
279
}
0 commit comments