58
58
import org .springframework .data .projection .EntityProjection ;
59
59
import org .springframework .data .projection .ProjectionFactory ;
60
60
import org .springframework .data .projection .SpelAwareProxyProjectionFactory ;
61
+ import org .springframework .data .util .Lazy ;
61
62
import org .springframework .util .Assert ;
62
63
63
64
import com .datastax .oss .driver .api .core .CqlIdentifier ;
@@ -353,10 +354,17 @@ public <T> List<T> select(Statement<?> statement, Class<T> entityClass) {
353
354
Assert .notNull (statement , "Statement must not be null" );
354
355
Assert .notNull (entityClass , "Entity type must not be null" );
355
356
356
- Function <Row , T > mapper = getMapper (EntityProjection .nonProjecting (entityClass ),
357
- EntityQueryUtils .getTableName (statement ));
357
+ return doSelect (statement , entityClass , getTableName (entityClass ), entityClass , QueryResultConverter .entity ());
358
+ }
359
+
360
+ <T , R > List <R > doSelect (Statement <?> statement , Class <?> entityClass , CqlIdentifier tableName , Class <T > returnType ,
361
+ QueryResultConverter <T , R > mappingFunction ) {
362
+
363
+ EntityProjection <T , ?> projection = entityOperations .introspectProjection (returnType , entityClass );
364
+
365
+ RowMapper <R > rowMapper = getRowMapper (projection , tableName , mappingFunction );
358
366
359
- return doQuery (statement , ( row , rowNum ) -> mapper . apply ( row ) );
367
+ return doQuery (statement , rowMapper );
360
368
}
361
369
362
370
@ Override
@@ -372,13 +380,14 @@ public <T> Slice<T> slice(Statement<?> statement, Class<T> entityClass) {
372
380
Assert .notNull (statement , "Statement must not be null" );
373
381
Assert .notNull (entityClass , "Entity type must not be null" );
374
382
375
- ResultSet resultSet = doQueryForResultSet (statement );
383
+ return doSlice (statement ,
384
+ getRowMapper (entityClass , EntityQueryUtils .getTableName (statement ), QueryResultConverter .entity ()));
385
+ }
376
386
377
- Function <Row , T > mapper = getMapper (EntityProjection .nonProjecting (entityClass ),
378
- EntityQueryUtils .getTableName (statement ));
387
+ <T > Slice <T > doSlice (Statement <?> statement , RowMapper <T > mapper ) {
379
388
380
- return EntityQueryUtils . readSlice ( resultSet , ( row , rowNum ) -> mapper . apply ( row ), 0 ,
381
- getEffectivePageSize (statement ));
389
+ ResultSet resultSet = doQueryForResultSet ( statement );
390
+ return EntityQueryUtils . readSlice ( resultSet , mapper , 0 , getEffectivePageSize (statement ));
382
391
}
383
392
384
393
@ Override
@@ -387,9 +396,17 @@ public <T> Stream<T> stream(Statement<?> statement, Class<T> entityClass) throws
387
396
Assert .notNull (statement , "Statement must not be null" );
388
397
Assert .notNull (entityClass , "Entity type must not be null" );
389
398
390
- Function <Row , T > mapper = getMapper (EntityProjection .nonProjecting (entityClass ),
391
- EntityQueryUtils .getTableName (statement ));
392
- return doQueryForStream (statement , (row , rowNum ) -> mapper .apply (row ));
399
+ return doStream (statement , entityClass , EntityQueryUtils .getTableName (statement ), entityClass ,
400
+ QueryResultConverter .entity ());
401
+ }
402
+
403
+ <T , R > Stream <R > doStream (Statement <?> statement , Class <?> entityClass , CqlIdentifier tableName , Class <T > returnType ,
404
+ QueryResultConverter <T , R > mappingFunction ) {
405
+
406
+ EntityProjection <T , ?> projection = entityOperations .introspectProjection (returnType , entityClass );
407
+
408
+ RowMapper <R > rowMapper = getRowMapper (projection , tableName , mappingFunction );
409
+ return doQueryForStream (statement , rowMapper );
393
410
}
394
411
395
412
// -------------------------------------------------------------------------
@@ -402,10 +419,11 @@ public <T> List<T> select(Query query, Class<T> entityClass) throws DataAccessEx
402
419
Assert .notNull (query , "Query must not be null" );
403
420
Assert .notNull (entityClass , "Entity type must not be null" );
404
421
405
- return doSelect (query , entityClass , getTableName (entityClass ), entityClass );
422
+ return doSelect (query , entityClass , getTableName (entityClass ), entityClass , QueryResultConverter . entity () );
406
423
}
407
424
408
- <T > List <T > doSelect (Query query , Class <?> entityClass , CqlIdentifier tableName , Class <T > returnType ) {
425
+ <T , R > List <R > doSelect (Query query , Class <?> entityClass , CqlIdentifier tableName , Class <T > returnType ,
426
+ QueryResultConverter <? super T , ? extends R > mappingFunction ) {
409
427
410
428
CassandraPersistentEntity <?> entity = getRequiredPersistentEntity (entityClass );
411
429
EntityProjection <T , ?> projection = entityOperations .introspectProjection (returnType , entityClass );
@@ -415,9 +433,9 @@ <T> List<T> doSelect(Query query, Class<?> entityClass, CqlIdentifier tableName,
415
433
Query queryToUse = query .columns (columns );
416
434
417
435
StatementBuilder <Select > select = getStatementFactory ().select (queryToUse , entity , tableName );
418
- Function < Row , T > mapper = getMapper (projection , tableName );
436
+ RowMapper < R > rowMapper = getRowMapper (projection , tableName , mappingFunction );
419
437
420
- return doQuery (select .build (), ( row , rowNum ) -> mapper . apply ( row ) );
438
+ return doQuery (select .build (), rowMapper );
421
439
}
422
440
423
441
@ Override
@@ -434,9 +452,24 @@ public <T> Slice<T> slice(Query query, Class<T> entityClass) throws DataAccessEx
434
452
Assert .notNull (query , "Query must not be null" );
435
453
Assert .notNull (entityClass , "Entity type must not be null" );
436
454
437
- StatementBuilder <Select > select = getStatementFactory ().select (query , getRequiredPersistentEntity (entityClass ));
455
+ return doSlice (query , entityClass , getRequiredPersistentEntity (entityClass ).getTableName (), entityClass ,
456
+ QueryResultConverter .entity ());
457
+ }
458
+
459
+ <T , R > Slice <R > doSlice (Query query , Class <?> entityClass , CqlIdentifier tableName , Class <T > returnType ,
460
+ QueryResultConverter <? super T , ? extends R > mappingFunction ) {
461
+
462
+ CassandraPersistentEntity <?> entity = getRequiredPersistentEntity (entityClass );
463
+ EntityProjection <T , ?> projection = entityOperations .introspectProjection (returnType , entityClass );
464
+ Columns columns = getStatementFactory ().computeColumnsForProjection (projection , query .getColumns (), entity ,
465
+ returnType );
466
+
467
+ Query queryToUse = query .columns (columns );
468
+
469
+ StatementBuilder <Select > select = getStatementFactory ().select (queryToUse , entity , tableName );
470
+ RowMapper <R > rowMapper = getRowMapper (projection , tableName , mappingFunction );
438
471
439
- return slice (select .build (), entityClass );
472
+ return doSlice (select .build (), rowMapper );
440
473
}
441
474
442
475
@ Override
@@ -445,17 +478,19 @@ public <T> Stream<T> stream(Query query, Class<T> entityClass) throws DataAccess
445
478
Assert .notNull (query , "Query must not be null" );
446
479
Assert .notNull (entityClass , "Entity type must not be null" );
447
480
448
- return doStream (query , entityClass , getTableName (entityClass ), entityClass );
481
+ return doStream (query , entityClass , getTableName (entityClass ), entityClass , QueryResultConverter . entity () );
449
482
}
450
483
451
- <T > Stream <T > doStream (Query query , Class <?> entityClass , CqlIdentifier tableName , Class <T > returnType ) {
484
+ <T , R > Stream <R > doStream (Query query , Class <?> entityClass , CqlIdentifier tableName , Class <T > returnType ,
485
+ QueryResultConverter <? super T , ? extends R > mappingFunction ) {
452
486
453
487
StatementBuilder <Select > select = getStatementFactory ().select (query , getRequiredPersistentEntity (entityClass ),
454
488
tableName );
455
489
EntityProjection <T , ?> projection = entityOperations .introspectProjection (returnType , entityClass );
456
490
457
- Function <Row , T > mapper = getMapper (projection , tableName );
458
- return doQueryForStream (select .build (), (row , rowNum ) -> mapper .apply (row ));
491
+ RowMapper <R > rowMapper = getRowMapper (projection , tableName , mappingFunction );
492
+
493
+ return doQueryForStream (select .build (), rowMapper );
459
494
}
460
495
461
496
@ Override
@@ -767,6 +802,16 @@ public <T> ExecutableSelect<T> query(Class<T> domainType) {
767
802
return new ExecutableSelectOperationSupport (this ).query (domainType );
768
803
}
769
804
805
+ @ Override
806
+ public UntypedSelect query (String cql ) {
807
+ return new ExecutableSelectOperationSupport (this ).query (cql );
808
+ }
809
+
810
+ @ Override
811
+ public UntypedSelect query (Statement <?> statement ) {
812
+ return new ExecutableSelectOperationSupport (this ).query (statement );
813
+ }
814
+
770
815
@ Override
771
816
public <T > ExecutableInsert <T > insert (Class <T > domainType ) {
772
817
return new ExecutableInsertOperationSupport (this ).insert (domainType );
@@ -909,6 +954,32 @@ public String getCql() {
909
954
return getCqlOperations ().execute (new GetConfiguredPageSize ());
910
955
}
911
956
957
+ @ SuppressWarnings ("unchecked" )
958
+ <T , R > RowMapper <R > getRowMapper (EntityProjection <T , ?> projection , CqlIdentifier tableName ,
959
+ QueryResultConverter <? super T , ? extends R > mappingFunction ) {
960
+
961
+ Function <Row , T > mapper = getMapper (projection , tableName );
962
+
963
+ return mappingFunction == QueryResultConverter .entity () ? (row , rowNum ) -> (R ) mapper .apply (row )
964
+ : (row , rowNum ) -> {
965
+ Lazy <T > reader = Lazy .of (() -> mapper .apply (row ));
966
+ return mappingFunction .mapRow (row , reader ::get );
967
+ };
968
+ }
969
+
970
+ @ SuppressWarnings ("unchecked" )
971
+ <T , R > RowMapper <R > getRowMapper (Class <T > domainClass , CqlIdentifier tableName ,
972
+ QueryResultConverter <? super T , ? extends R > mappingFunction ) {
973
+
974
+ Function <Row , T > mapper = getMapper (EntityProjection .nonProjecting (domainClass ), tableName );
975
+
976
+ return mappingFunction == QueryResultConverter .entity () ? (row , rowNum ) -> (R ) mapper .apply (row )
977
+ : (row , rowNum ) -> {
978
+ Lazy <T > reader = Lazy .of (() -> mapper .apply (row ));
979
+ return mappingFunction .mapRow (row , reader ::get );
980
+ };
981
+ }
982
+
912
983
@ SuppressWarnings ("unchecked" )
913
984
private <T > Function <Row , T > getMapper (EntityProjection <T , ?> projection , CqlIdentifier tableName ) {
914
985
0 commit comments