@@ -76,6 +76,7 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
76
76
private final JdbcConverter converter ;
77
77
private final NamedParameterJdbcOperations operations ;
78
78
private final BatchJdbcOperations batchOperations ;
79
+ private final SqlParametersFactory sqlParametersFactory ;
79
80
80
81
/**
81
82
* Creates a {@link DefaultDataAccessStrategy}
@@ -87,24 +88,26 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
87
88
* @since 1.1
88
89
*/
89
90
public DefaultDataAccessStrategy (SqlGeneratorSource sqlGeneratorSource , RelationalMappingContext context ,
90
- JdbcConverter converter , NamedParameterJdbcOperations operations ) {
91
- this (sqlGeneratorSource , context , converter , operations , new BatchJdbcOperations (operations .getJdbcOperations ()));
91
+ JdbcConverter converter , NamedParameterJdbcOperations operations , SqlParametersFactory sqlParametersFactory ) {
92
+ this (sqlGeneratorSource , context , converter , operations , new BatchJdbcOperations (operations .getJdbcOperations ()), sqlParametersFactory );
92
93
}
93
94
94
95
DefaultDataAccessStrategy (SqlGeneratorSource sqlGeneratorSource , RelationalMappingContext context ,
95
96
JdbcConverter converter , NamedParameterJdbcOperations operations ,
96
- BatchJdbcOperations batchOperations ) {
97
+ BatchJdbcOperations batchOperations , SqlParametersFactory sqlParametersFactory ) {
97
98
98
99
Assert .notNull (sqlGeneratorSource , "SqlGeneratorSource must not be null" );
99
100
Assert .notNull (context , "RelationalMappingContext must not be null" );
100
101
Assert .notNull (converter , "JdbcConverter must not be null" );
101
102
Assert .notNull (operations , "NamedParameterJdbcOperations must not be null" );
103
+ Assert .notNull (sqlParametersFactory , "SqlParametersFactory must not be null" );
102
104
103
105
this .sqlGeneratorSource = sqlGeneratorSource ;
104
106
this .context = context ;
105
107
this .converter = converter ;
106
108
this .operations = operations ;
107
109
this .batchOperations = batchOperations ;
110
+ this .sqlParametersFactory = sqlParametersFactory ;
108
111
}
109
112
110
113
/*
@@ -114,24 +117,12 @@ public DefaultDataAccessStrategy(SqlGeneratorSource sqlGeneratorSource, Relation
114
117
@ Override
115
118
public <T > Object insert (T instance , Class <T > domainType , Identifier identifier , boolean includeId ) {
116
119
117
- SqlGenerator sqlGenerator = sql (domainType );
118
- RelationalPersistentEntity <T > persistentEntity = getRequiredPersistentEntity (domainType );
119
-
120
- SqlIdentifierParameterSource parameterSource = getParameterSource (instance , persistentEntity , "" ,
121
- PersistentProperty ::isIdProperty , getIdentifierProcessing ());
122
-
123
- identifier .forEach ((name , value , type ) -> addConvertedPropertyValue (parameterSource , name , value , type ));
124
-
125
- Object idValue = getIdValueOrNull (instance , persistentEntity );
126
- if (idValue != null ) {
120
+ SqlIdentifierParameterSource parameterSource = sqlParametersFactory .getInsert (instance , domainType , identifier );
127
121
128
- RelationalPersistentProperty idProperty = persistentEntity .getRequiredIdProperty ();
129
- addConvertedPropertyValue (parameterSource , idProperty , idValue , idProperty .getColumnName ());
130
- }
131
-
132
- String insertSql = sqlGenerator .getInsert (parameterSource .getIdentifiers ());
122
+ String insertSql = sql (domainType ).getInsert (parameterSource .getIdentifiers ());
133
123
134
124
if (!includeId ) {
125
+ RelationalPersistentEntity <T > persistentEntity = getRequiredPersistentEntity (domainType );
135
126
return executeInsertAndReturnGeneratedId (persistentEntity , parameterSource , insertSql );
136
127
} else {
137
128
@@ -143,9 +134,9 @@ public <T> Object insert(T instance, Class<T> domainType, Identifier identifier,
143
134
@ Override
144
135
public <T > Object [] insert (List <RecordDescriptor <T >> recordDescriptors , Class <T > domainType , boolean includeId ) {
145
136
146
- RelationalPersistentEntity < T > persistentEntity = getRequiredPersistentEntity ( domainType );
137
+ Assert . notEmpty ( recordDescriptors , "recordDescriptors must contain at least one recordDescriptor" );
147
138
SqlIdentifierParameterSource [] sqlParameterSources = recordDescriptors .stream ()
148
- .map (recordDescriptor -> getParameterSource (recordDescriptor , persistentEntity ))
139
+ .map (recordDescriptor -> sqlParametersFactory . getInsert (recordDescriptor . getInstance (), domainType , recordDescriptor . getIdentifier () ))
149
140
.toArray (SqlIdentifierParameterSource []::new );
150
141
151
142
String insertSql = sql (domainType ).getInsert (sqlParameterSources [0 ].getIdentifiers ());
@@ -158,6 +149,7 @@ public <T> Object[] insert(List<RecordDescriptor<T>> recordDescriptors, Class<T>
158
149
159
150
IdGeneration idGeneration = sqlGeneratorSource .getDialect ().getIdGeneration ();
160
151
152
+ RelationalPersistentEntity <T > persistentEntity = getRequiredPersistentEntity (domainType );
161
153
if (idGeneration .driverRequiresKeyColumnNames ()) {
162
154
163
155
String [] keyColumnNames = getKeyColumnNames (persistentEntity .getType ());
@@ -169,6 +161,7 @@ public <T> Object[] insert(List<RecordDescriptor<T>> recordDescriptors, Class<T>
169
161
} else {
170
162
batchOperations .insert (insertSql , sqlParameterSources , holder );
171
163
}
164
+ // TODO: Is this needed?
172
165
if (!persistentEntity .hasIdProperty ()) {
173
166
return new Object [sqlParameterSources .length ];
174
167
}
@@ -183,29 +176,13 @@ public <T> Object[] insert(List<RecordDescriptor<T>> recordDescriptors, Class<T>
183
176
} else {
184
177
id = keys .entrySet ().stream ().findFirst () //
185
178
.map (Map .Entry ::getValue ) //
186
- // TODO: Missing a test for this
187
- .orElse (null );
179
+ .orElseThrow (() -> new IllegalStateException ("KeyHolder contains an empty key list." ));
188
180
}
189
181
ids [i ] = id ;
190
182
}
191
183
return ids ;
192
184
}
193
185
194
- private <T > SqlIdentifierParameterSource getParameterSource (RecordDescriptor <T > recordDescriptor , RelationalPersistentEntity <T > persistentEntity ) {
195
- SqlIdentifierParameterSource parameterSource = getParameterSource (recordDescriptor .getInstance (), persistentEntity , "" ,
196
- PersistentProperty ::isIdProperty , getIdentifierProcessing ());
197
-
198
- recordDescriptor .getIdentifier ().forEach ((name , value , type ) -> addConvertedPropertyValue (parameterSource , name , value , type ));
199
-
200
- Object idValue = getIdValueOrNull (recordDescriptor .getInstance (), persistentEntity );
201
- if (idValue != null ) {
202
-
203
- RelationalPersistentProperty idProperty = persistentEntity .getRequiredIdProperty ();
204
- addConvertedPropertyValue (parameterSource , idProperty , idValue , idProperty .getColumnName ());
205
- }
206
- return parameterSource ;
207
- }
208
-
209
186
@ Nullable
210
187
private <T > Object executeInsertAndReturnGeneratedId (RelationalPersistentEntity <T > persistentEntity , SqlIdentifierParameterSource parameterSource , String insertSql ) {
211
188
@@ -234,10 +211,7 @@ private <T> Object executeInsertAndReturnGeneratedId(RelationalPersistentEntity<
234
211
*/
235
212
@ Override
236
213
public <S > boolean update (S instance , Class <S > domainType ) {
237
-
238
- RelationalPersistentEntity <S > persistentEntity = getRequiredPersistentEntity (domainType );
239
- return operations .update (sql (domainType ).getUpdate (),
240
- getParameterSource (instance , persistentEntity , "" , Predicates .includeAll (), getIdentifierProcessing ())) != 0 ;
214
+ return operations .update (sql (domainType ).getUpdate (), sqlParametersFactory .getUpdate (instance , domainType )) != 0 ;
241
215
}
242
216
243
217
/*
@@ -250,8 +224,7 @@ public <S> boolean updateWithVersion(S instance, Class<S> domainType, Number pre
250
224
RelationalPersistentEntity <S > persistentEntity = getRequiredPersistentEntity (domainType );
251
225
252
226
// Adjust update statement to set the new version and use the old version in where clause.
253
- SqlIdentifierParameterSource parameterSource = getParameterSource (instance , persistentEntity , "" ,
254
- Predicates .includeAll (), getIdentifierProcessing ());
227
+ SqlIdentifierParameterSource parameterSource = sqlParametersFactory .getUpdate (instance , domainType );
255
228
parameterSource .addValue (VERSION_SQL_PARAMETER , previousVersion );
256
229
257
230
int affectedRows = operations .update (sql (domainType ).getUpdateWithVersion (), parameterSource );
@@ -502,67 +475,6 @@ public <T> Iterable<T> findAll(Class<T> domainType, Pageable pageable) {
502
475
return operations .query (sql (domainType ).getFindAll (pageable ), (RowMapper <T >) getEntityRowMapper (domainType ));
503
476
}
504
477
505
- private <S , T > SqlIdentifierParameterSource getParameterSource (@ Nullable S instance ,
506
- RelationalPersistentEntity <S > persistentEntity , String prefix ,
507
- Predicate <RelationalPersistentProperty > skipProperty , IdentifierProcessing identifierProcessing ) {
508
-
509
- SqlIdentifierParameterSource parameters = new SqlIdentifierParameterSource (identifierProcessing );
510
-
511
- PersistentPropertyAccessor <S > propertyAccessor = instance != null ? persistentEntity .getPropertyAccessor (instance )
512
- : NoValuePropertyAccessor .instance ();
513
-
514
- persistentEntity .doWithAll (property -> {
515
-
516
- if (skipProperty .test (property ) || !property .isWritable ()) {
517
- return ;
518
- }
519
- if (property .isEntity () && !property .isEmbedded ()) {
520
- return ;
521
- }
522
-
523
- if (property .isEmbedded ()) {
524
-
525
- Object value = propertyAccessor .getProperty (property );
526
- RelationalPersistentEntity <?> embeddedEntity = context .getPersistentEntity (property .getType ());
527
- SqlIdentifierParameterSource additionalParameters = getParameterSource ((T ) value ,
528
- (RelationalPersistentEntity <T >) embeddedEntity , prefix + property .getEmbeddedPrefix (), skipProperty ,
529
- identifierProcessing );
530
- parameters .addAll (additionalParameters );
531
- } else {
532
-
533
- Object value = propertyAccessor .getProperty (property );
534
- SqlIdentifier paramName = property .getColumnName ().transform (prefix ::concat );
535
-
536
- addConvertedPropertyValue (parameters , property , value , paramName );
537
- }
538
- });
539
-
540
- return parameters ;
541
- }
542
-
543
- /**
544
- * Returns the id value if its not a primitive zero. Returns {@literal null} if the id value is null or a primitive
545
- * zero.
546
- */
547
- @ Nullable
548
- @ SuppressWarnings ("unchecked" )
549
- private <S , ID > ID getIdValueOrNull (S instance , RelationalPersistentEntity <S > persistentEntity ) {
550
-
551
- ID idValue = (ID ) persistentEntity .getIdentifierAccessor (instance ).getIdentifier ();
552
-
553
- return isIdPropertyNullOrScalarZero (idValue , persistentEntity ) ? null : idValue ;
554
- }
555
-
556
- private static <S , ID > boolean isIdPropertyNullOrScalarZero (@ Nullable ID idValue ,
557
- RelationalPersistentEntity <S > persistentEntity ) {
558
-
559
- RelationalPersistentProperty idProperty = persistentEntity .getIdProperty ();
560
- return idValue == null //
561
- || idProperty == null //
562
- || (idProperty .getType () == int .class && idValue .equals (0 )) //
563
- || (idProperty .getType () == long .class && idValue .equals (0L ));
564
- }
565
-
566
478
@ Nullable
567
479
private <S > Object getIdFromHolder (KeyHolder holder , RelationalPersistentEntity <S > persistentEntity ) {
568
480
@@ -599,6 +511,7 @@ private RowMapper<?> getMapEntityRowMapper(PersistentPropertyPathExtension path,
599
511
return new MapEntityRowMapper <>(path , converter , identifier , keyColumn , getIdentifierProcessing ());
600
512
}
601
513
514
+ // TODO: Move to SqlParametersFactory
602
515
private <T > SqlIdentifierParameterSource createIdParameterSource (Object id , Class <T > domainType ) {
603
516
604
517
SqlIdentifierParameterSource parameterSource = new SqlIdentifierParameterSource (getIdentifierProcessing ());
@@ -687,47 +600,4 @@ private <T> String[] getKeyColumnNames(Class<T> domainType) {
687
600
return new String [] { idColumn .getReference (getIdentifierProcessing ()) };
688
601
}
689
602
690
- /**
691
- * Utility to create {@link Predicate}s.
692
- */
693
- static class Predicates {
694
-
695
- /**
696
- * Include all {@link Predicate} returning {@literal false} to never skip a property.
697
- *
698
- * @return the include all {@link Predicate}.
699
- */
700
- static Predicate <RelationalPersistentProperty > includeAll () {
701
- return it -> false ;
702
- }
703
- }
704
-
705
- /**
706
- * A {@link PersistentPropertyAccessor} implementation always returning null
707
- *
708
- * @param <T>
709
- */
710
- static class NoValuePropertyAccessor <T > implements PersistentPropertyAccessor <T > {
711
-
712
- private static final NoValuePropertyAccessor INSTANCE = new NoValuePropertyAccessor ();
713
-
714
- static <T > NoValuePropertyAccessor <T > instance () {
715
- return INSTANCE ;
716
- }
717
-
718
- @ Override
719
- public void setProperty (PersistentProperty <?> property , @ Nullable Object value ) {
720
- throw new UnsupportedOperationException ("Cannot set value on 'null' target object." );
721
- }
722
-
723
- @ Override
724
- public Object getProperty (PersistentProperty <?> property ) {
725
- return null ;
726
- }
727
-
728
- @ Override
729
- public T getBean () {
730
- return null ;
731
- }
732
- }
733
603
}
0 commit comments