@@ -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
@@ -145,9 +136,8 @@ public <T> Object[] insert(List<RecordDescriptor<T>> recordDescriptors, Class<T>
145
136
// TODO: A better name for this may be the inverse (generatedIdExpected)
146
137
boolean includeId ) {
147
138
148
- RelationalPersistentEntity <T > persistentEntity = getRequiredPersistentEntity (domainType );
149
139
SqlIdentifierParameterSource [] sqlParameterSources = recordDescriptors .stream ()
150
- .map (recordDescriptor -> getParameterSource (recordDescriptor , persistentEntity ))
140
+ .map (recordDescriptor -> sqlParametersFactory . getInsert (recordDescriptor . getInstance (), domainType , recordDescriptor . getIdentifier () ))
151
141
.toArray (SqlIdentifierParameterSource []::new );
152
142
153
143
String insertSql = sql (domainType ).getInsert (sqlParameterSources [0 ].getIdentifiers ());
@@ -160,6 +150,7 @@ public <T> Object[] insert(List<RecordDescriptor<T>> recordDescriptors, Class<T>
160
150
161
151
IdGeneration idGeneration = sqlGeneratorSource .getDialect ().getIdGeneration ();
162
152
153
+ RelationalPersistentEntity <T > persistentEntity = getRequiredPersistentEntity (domainType );
163
154
if (idGeneration .driverRequiresKeyColumnNames ()) {
164
155
165
156
String [] keyColumnNames = getKeyColumnNames (persistentEntity .getType ());
@@ -171,6 +162,7 @@ public <T> Object[] insert(List<RecordDescriptor<T>> recordDescriptors, Class<T>
171
162
} else {
172
163
batchOperations .insert (insertSql , sqlParameterSources , holder );
173
164
}
165
+ // TODO: Is this needed?
174
166
if (!persistentEntity .hasIdProperty ()) {
175
167
return new Object [sqlParameterSources .length ];
176
168
}
@@ -185,29 +177,13 @@ public <T> Object[] insert(List<RecordDescriptor<T>> recordDescriptors, Class<T>
185
177
} else {
186
178
id = keys .entrySet ().stream ().findFirst () //
187
179
.map (Map .Entry ::getValue ) //
188
- // TODO: Missing a test for this
189
- .orElse (null );
180
+ .orElseThrow (() -> new IllegalStateException ("KeyHolder contains an empty key list." ));
190
181
}
191
182
ids [i ] = id ;
192
183
}
193
184
return ids ;
194
185
}
195
186
196
- private <T > SqlIdentifierParameterSource getParameterSource (RecordDescriptor <T > recordDescriptor , RelationalPersistentEntity <T > persistentEntity ) {
197
- SqlIdentifierParameterSource parameterSource = getParameterSource (recordDescriptor .getInstance (), persistentEntity , "" ,
198
- PersistentProperty ::isIdProperty , getIdentifierProcessing ());
199
-
200
- recordDescriptor .getIdentifier ().forEach ((name , value , type ) -> addConvertedPropertyValue (parameterSource , name , value , type ));
201
-
202
- Object idValue = getIdValueOrNull (recordDescriptor .getInstance (), persistentEntity );
203
- if (idValue != null ) {
204
-
205
- RelationalPersistentProperty idProperty = persistentEntity .getRequiredIdProperty ();
206
- addConvertedPropertyValue (parameterSource , idProperty , idValue , idProperty .getColumnName ());
207
- }
208
- return parameterSource ;
209
- }
210
-
211
187
@ Nullable
212
188
private <T > Object executeInsertAndReturnGeneratedId (RelationalPersistentEntity <T > persistentEntity , SqlIdentifierParameterSource parameterSource , String insertSql ) {
213
189
@@ -236,10 +212,7 @@ private <T> Object executeInsertAndReturnGeneratedId(RelationalPersistentEntity<
236
212
*/
237
213
@ Override
238
214
public <S > boolean update (S instance , Class <S > domainType ) {
239
-
240
- RelationalPersistentEntity <S > persistentEntity = getRequiredPersistentEntity (domainType );
241
- return operations .update (sql (domainType ).getUpdate (),
242
- getParameterSource (instance , persistentEntity , "" , Predicates .includeAll (), getIdentifierProcessing ())) != 0 ;
215
+ return operations .update (sql (domainType ).getUpdate (), sqlParametersFactory .getUpdate (instance , domainType )) != 0 ;
243
216
}
244
217
245
218
/*
@@ -252,8 +225,7 @@ public <S> boolean updateWithVersion(S instance, Class<S> domainType, Number pre
252
225
RelationalPersistentEntity <S > persistentEntity = getRequiredPersistentEntity (domainType );
253
226
254
227
// Adjust update statement to set the new version and use the old version in where clause.
255
- SqlIdentifierParameterSource parameterSource = getParameterSource (instance , persistentEntity , "" ,
256
- Predicates .includeAll (), getIdentifierProcessing ());
228
+ SqlIdentifierParameterSource parameterSource = sqlParametersFactory .getUpdate (instance , domainType );
257
229
parameterSource .addValue (VERSION_SQL_PARAMETER , previousVersion );
258
230
259
231
int affectedRows = operations .update (sql (domainType ).getUpdateWithVersion (), parameterSource );
@@ -504,67 +476,6 @@ public <T> Iterable<T> findAll(Class<T> domainType, Pageable pageable) {
504
476
return operations .query (sql (domainType ).getFindAll (pageable ), (RowMapper <T >) getEntityRowMapper (domainType ));
505
477
}
506
478
507
- private <S , T > SqlIdentifierParameterSource getParameterSource (@ Nullable S instance ,
508
- RelationalPersistentEntity <S > persistentEntity , String prefix ,
509
- Predicate <RelationalPersistentProperty > skipProperty , IdentifierProcessing identifierProcessing ) {
510
-
511
- SqlIdentifierParameterSource parameters = new SqlIdentifierParameterSource (identifierProcessing );
512
-
513
- PersistentPropertyAccessor <S > propertyAccessor = instance != null ? persistentEntity .getPropertyAccessor (instance )
514
- : NoValuePropertyAccessor .instance ();
515
-
516
- persistentEntity .doWithAll (property -> {
517
-
518
- if (skipProperty .test (property ) || !property .isWritable ()) {
519
- return ;
520
- }
521
- if (property .isEntity () && !property .isEmbedded ()) {
522
- return ;
523
- }
524
-
525
- if (property .isEmbedded ()) {
526
-
527
- Object value = propertyAccessor .getProperty (property );
528
- RelationalPersistentEntity <?> embeddedEntity = context .getPersistentEntity (property .getType ());
529
- SqlIdentifierParameterSource additionalParameters = getParameterSource ((T ) value ,
530
- (RelationalPersistentEntity <T >) embeddedEntity , prefix + property .getEmbeddedPrefix (), skipProperty ,
531
- identifierProcessing );
532
- parameters .addAll (additionalParameters );
533
- } else {
534
-
535
- Object value = propertyAccessor .getProperty (property );
536
- SqlIdentifier paramName = property .getColumnName ().transform (prefix ::concat );
537
-
538
- addConvertedPropertyValue (parameters , property , value , paramName );
539
- }
540
- });
541
-
542
- return parameters ;
543
- }
544
-
545
- /**
546
- * Returns the id value if its not a primitive zero. Returns {@literal null} if the id value is null or a primitive
547
- * zero.
548
- */
549
- @ Nullable
550
- @ SuppressWarnings ("unchecked" )
551
- private <S , ID > ID getIdValueOrNull (S instance , RelationalPersistentEntity <S > persistentEntity ) {
552
-
553
- ID idValue = (ID ) persistentEntity .getIdentifierAccessor (instance ).getIdentifier ();
554
-
555
- return isIdPropertyNullOrScalarZero (idValue , persistentEntity ) ? null : idValue ;
556
- }
557
-
558
- private static <S , ID > boolean isIdPropertyNullOrScalarZero (@ Nullable ID idValue ,
559
- RelationalPersistentEntity <S > persistentEntity ) {
560
-
561
- RelationalPersistentProperty idProperty = persistentEntity .getIdProperty ();
562
- return idValue == null //
563
- || idProperty == null //
564
- || (idProperty .getType () == int .class && idValue .equals (0 )) //
565
- || (idProperty .getType () == long .class && idValue .equals (0L ));
566
- }
567
-
568
479
@ Nullable
569
480
private <S > Object getIdFromHolder (KeyHolder holder , RelationalPersistentEntity <S > persistentEntity ) {
570
481
@@ -601,6 +512,7 @@ private RowMapper<?> getMapEntityRowMapper(PersistentPropertyPathExtension path,
601
512
return new MapEntityRowMapper <>(path , converter , identifier , keyColumn , getIdentifierProcessing ());
602
513
}
603
514
515
+ // TODO: Move to SqlParametersFactory
604
516
private <T > SqlIdentifierParameterSource createIdParameterSource (Object id , Class <T > domainType ) {
605
517
606
518
SqlIdentifierParameterSource parameterSource = new SqlIdentifierParameterSource (getIdentifierProcessing ());
@@ -689,47 +601,4 @@ private <T> String[] getKeyColumnNames(Class<T> domainType) {
689
601
return new String [] { idColumn .getReference (getIdentifierProcessing ()) };
690
602
}
691
603
692
- /**
693
- * Utility to create {@link Predicate}s.
694
- */
695
- static class Predicates {
696
-
697
- /**
698
- * Include all {@link Predicate} returning {@literal false} to never skip a property.
699
- *
700
- * @return the include all {@link Predicate}.
701
- */
702
- static Predicate <RelationalPersistentProperty > includeAll () {
703
- return it -> false ;
704
- }
705
- }
706
-
707
- /**
708
- * A {@link PersistentPropertyAccessor} implementation always returning null
709
- *
710
- * @param <T>
711
- */
712
- static class NoValuePropertyAccessor <T > implements PersistentPropertyAccessor <T > {
713
-
714
- private static final NoValuePropertyAccessor INSTANCE = new NoValuePropertyAccessor ();
715
-
716
- static <T > NoValuePropertyAccessor <T > instance () {
717
- return INSTANCE ;
718
- }
719
-
720
- @ Override
721
- public void setProperty (PersistentProperty <?> property , @ Nullable Object value ) {
722
- throw new UnsupportedOperationException ("Cannot set value on 'null' target object." );
723
- }
724
-
725
- @ Override
726
- public Object getProperty (PersistentProperty <?> property ) {
727
- return null ;
728
- }
729
-
730
- @ Override
731
- public T getBean () {
732
- return null ;
733
- }
734
- }
735
604
}
0 commit comments