37
37
import java .util .LinkedHashSet ;
38
38
import java .util .List ;
39
39
import java .util .Map ;
40
- import java .util .Set ;
41
40
import java .util .concurrent .atomic .AtomicBoolean ;
42
41
import java .util .function .BiFunction ;
43
42
import java .util .function .Function ;
49
48
import org .reactivestreams .Publisher ;
50
49
51
50
import org .springframework .dao .DataAccessException ;
51
+ import org .springframework .dao .InvalidDataAccessApiUsageException ;
52
52
import org .springframework .data .domain .Pageable ;
53
53
import org .springframework .data .domain .Sort ;
54
54
import org .springframework .data .r2dbc .UncategorizedR2dbcException ;
57
57
import org .springframework .data .r2dbc .function .connectionfactory .ConnectionProxy ;
58
58
import org .springframework .data .r2dbc .function .convert .ColumnMapRowMapper ;
59
59
import org .springframework .data .r2dbc .support .R2dbcExceptionTranslator ;
60
+ import org .springframework .data .relational .core .sql .Insert ;
60
61
import org .springframework .lang .Nullable ;
61
62
import org .springframework .util .Assert ;
62
63
@@ -336,9 +337,17 @@ <T> FetchSpec<T> exchange(String sql, BiFunction<Row, RowMetadata, T> mappingFun
336
337
logger .debug ("Executing SQL statement [" + sql + "]" );
337
338
}
338
339
340
+ if (sqlSupplier instanceof PreparedOperation <?>) {
341
+ return ((PreparedOperation <?>) sqlSupplier ).bind (it .createStatement (sql ));
342
+ }
343
+
339
344
BindableOperation operation = namedParameters .expand (sql , dataAccessStrategy .getBindMarkersFactory (),
340
345
new MapBindParameterSource (byName ));
341
346
347
+ if (logger .isTraceEnabled ()) {
348
+ logger .trace ("Expanded SQL [" + operation .toQuery () + "]" );
349
+ }
350
+
342
351
Statement statement = it .createStatement (operation .toQuery ());
343
352
344
353
byName .forEach ((name , o ) -> {
@@ -366,6 +375,7 @@ <T> FetchSpec<T> exchange(String sql, BiFunction<Row, RowMetadata, T> mappingFun
366
375
367
376
public ExecuteSpecSupport bind (int index , Object value ) {
368
377
378
+ assertNotPreparedOperation ();
369
379
Assert .notNull (value , () -> String .format ("Value at index %d must not be null. Use bindNull(…) instead." , index ));
370
380
371
381
Map <Integer , SettableValue > byIndex = new LinkedHashMap <>(this .byIndex );
@@ -376,6 +386,8 @@ public ExecuteSpecSupport bind(int index, Object value) {
376
386
377
387
public ExecuteSpecSupport bindNull (int index , Class <?> type ) {
378
388
389
+ assertNotPreparedOperation ();
390
+
379
391
Map <Integer , SettableValue > byIndex = new LinkedHashMap <>(this .byIndex );
380
392
byIndex .put (index , SettableValue .empty (type ));
381
393
@@ -384,6 +396,8 @@ public ExecuteSpecSupport bindNull(int index, Class<?> type) {
384
396
385
397
public ExecuteSpecSupport bind (String name , Object value ) {
386
398
399
+ assertNotPreparedOperation ();
400
+
387
401
Assert .hasText (name , "Parameter name must not be null or empty!" );
388
402
Assert .notNull (value ,
389
403
() -> String .format ("Value for parameter %s must not be null. Use bindNull(…) instead." , name ));
@@ -396,6 +410,7 @@ public ExecuteSpecSupport bind(String name, Object value) {
396
410
397
411
public ExecuteSpecSupport bindNull (String name , Class <?> type ) {
398
412
413
+ assertNotPreparedOperation ();
399
414
Assert .hasText (name , "Parameter name must not be null or empty!" );
400
415
401
416
Map <String , SettableValue > byName = new LinkedHashMap <>(this .byName );
@@ -404,6 +419,12 @@ public ExecuteSpecSupport bindNull(String name, Class<?> type) {
404
419
return createInstance (this .byIndex , byName , this .sqlSupplier );
405
420
}
406
421
422
+ private void assertNotPreparedOperation () {
423
+ if (sqlSupplier instanceof PreparedOperation <?>) {
424
+ throw new InvalidDataAccessApiUsageException ("Cannot add bindings to a PreparedOperation" );
425
+ }
426
+ }
427
+
407
428
protected ExecuteSpecSupport createInstance (Map <Integer , SettableValue > byIndex , Map <String , SettableValue > byName ,
408
429
Supplier <String > sqlSupplier ) {
409
430
return new ExecuteSpecSupport (byIndex , byName , sqlSupplier );
@@ -881,20 +902,19 @@ private <R> FetchSpec<R> exchange(BiFunction<Row, RowMetadata, R> mappingFunctio
881
902
throw new IllegalStateException ("Insert fields is empty!" );
882
903
}
883
904
884
- BindableOperation bindableInsert = dataAccessStrategy .insertAndReturnGeneratedKeys (table , byName .keySet ());
905
+ PreparedOperation <Insert > operation = dataAccessStrategy .getStatements ().insert (table , Collections .emptyList (),
906
+ it -> {
907
+ byName .forEach (it ::bind );
908
+ });
885
909
886
- String sql = bindableInsert .toQuery ();
910
+ String sql = operation .toQuery ();
887
911
Function <Connection , Statement > insertFunction = it -> {
888
912
889
913
if (logger .isDebugEnabled ()) {
890
914
logger .debug ("Executing SQL statement [" + sql + "]" );
891
915
}
892
916
893
- Statement statement = it .createStatement (sql ).returnGeneratedValues ();
894
-
895
- byName .forEach ((k , v ) -> bindableInsert .bind (statement , k , v ));
896
-
897
- return statement ;
917
+ return operation .bind (it .createStatement (sql ));
898
918
};
899
919
900
920
Function <Connection , Flux <Result >> resultFunction = it -> Flux .from (insertFunction .apply (it ).execute ());
@@ -998,34 +1018,25 @@ private <MR> FetchSpec<MR> exchange(Object toInsert, BiFunction<Row, RowMetadata
998
1018
999
1019
OutboundRow outboundRow = dataAccessStrategy .getOutboundRow (toInsert );
1000
1020
1001
- Set <String > columns = new LinkedHashSet <>();
1002
-
1003
- outboundRow .forEach ((k , v ) -> {
1004
-
1005
- if (v .hasValue ()) {
1006
- columns .add (k );
1007
- }
1008
- });
1021
+ PreparedOperation <Insert > operation = dataAccessStrategy .getStatements ().insert (table , Collections .emptyList (),
1022
+ it -> {
1023
+ outboundRow .forEach ((k , v ) -> {
1009
1024
1010
- BindableOperation bindableInsert = dataAccessStrategy .insertAndReturnGeneratedKeys (table , columns );
1025
+ if (v .hasValue ()) {
1026
+ it .bind (k , v );
1027
+ }
1028
+ });
1029
+ });
1011
1030
1012
- String sql = bindableInsert .toQuery ();
1031
+ String sql = operation .toQuery ();
1013
1032
1014
1033
Function <Connection , Statement > insertFunction = it -> {
1015
1034
1016
1035
if (logger .isDebugEnabled ()) {
1017
1036
logger .debug ("Executing SQL statement [" + sql + "]" );
1018
1037
}
1019
1038
1020
- Statement statement = it .createStatement (sql ).returnGeneratedValues ();
1021
-
1022
- outboundRow .forEach ((k , v ) -> {
1023
- if (v .hasValue ()) {
1024
- bindableInsert .bind (statement , k , v );
1025
- }
1026
- });
1027
-
1028
- return statement ;
1039
+ return operation .bind (it .createStatement (sql ));
1029
1040
};
1030
1041
1031
1042
Function <Connection , Flux <Result >> resultFunction = it -> Flux .from (insertFunction .apply (it ).execute ());
0 commit comments