1818import java .util .Collection ;
1919import java .util .List ;
2020import java .util .Map ;
21+ import java .util .Spliterator ;
22+ import java .util .concurrent .atomic .AtomicInteger ;
23+ import java .util .function .Consumer ;
2124import java .util .function .Function ;
25+ import java .util .stream .Stream ;
2226import java .util .stream .StreamSupport ;
2327
2428import org .springframework .dao .DataAccessException ;
@@ -316,6 +320,16 @@ public <T> List<T> query(Statement<?> statement, RowMapper<T> rowMapper) throws
316320 return query (statement , newResultSetExtractor (rowMapper ));
317321 }
318322
323+ /*
324+ * (non-Javadoc)
325+ * @see org.springframework.data.cassandra.core.cqlOperations#queryForStream(com.datastax.oss.driver.api.core.cql.Statement, org.springframework.data.cassandra.core.cql.RowMapper)
326+ */
327+ @ Override
328+ public <T > Stream <T > queryForStream (Statement <?> statement , RowMapper <T > rowMapper ) throws DataAccessException {
329+ // noinspection ConstantConditions
330+ return query (statement , newStreamExtractor (rowMapper ));
331+ }
332+
319333 /*
320334 * (non-Javadoc)
321335 * @see org.springframework.data.cassandra.core.cqlOperations#queryForList(com.datastax.oss.driver.api.core.cql.Statement)
@@ -342,7 +356,6 @@ public <T> List<T> queryForList(Statement<?> statement, Class<T> elementType) th
342356 */
343357 @ Override
344358 public Map <String , Object > queryForMap (Statement <?> statement ) throws DataAccessException {
345- // noinspection ConstantConditions
346359 return queryForObject (statement , newColumnMapRowMapper ());
347360 }
348361
@@ -485,6 +498,17 @@ public <T> List<T> query(PreparedStatementCreator preparedStatementCreator, RowM
485498 return query (preparedStatementCreator , null , newResultSetExtractor (rowMapper ));
486499 }
487500
501+ /*
502+ * (non-Javadoc)
503+ * @see org.springframework.data.cassandra.core.cqlOperations#query(org.springframework.data.cassandra.core.cql.PreparedStatementCreator, org.springframework.data.cassandra.core.cql.RowMapper)
504+ */
505+ @ Override
506+ public <T > Stream <T > queryForStream (PreparedStatementCreator preparedStatementCreator , RowMapper <T > rowMapper )
507+ throws DataAccessException {
508+ // noinspection ConstantConditions
509+ return query (preparedStatementCreator , null , newStreamExtractor (rowMapper ));
510+ }
511+
488512 /*
489513 * (non-Javadoc)
490514 * @see org.springframework.data.cassandra.core.cqlOperations#query(org.springframework.data.cassandra.core.cql.PreparedStatementCreator, org.springframework.data.cassandra.core.cql.PreparedStatementBinder, org.springframework.data.cassandra.core.cql.ResultSetExtractor)
@@ -544,6 +568,17 @@ public <T> List<T> query(PreparedStatementCreator preparedStatementCreator, @Nul
544568 return query (preparedStatementCreator , psb , newResultSetExtractor (rowMapper ));
545569 }
546570
571+ /*
572+ * (non-Javadoc)
573+ * @see org.springframework.data.cassandra.core.cqlOperations#queryForStream(org.springframework.data.cassandra.core.cql.PreparedStatementCreator, org.springframework.data.cassandra.core.cql.PreparedStatementBinder, org.springframework.data.cassandra.core.cql.RowMapper)
574+ */
575+ @ Override
576+ public <T > Stream <T > queryForStream (PreparedStatementCreator preparedStatementCreator ,
577+ @ Nullable PreparedStatementBinder psb , RowMapper <T > rowMapper ) throws DataAccessException {
578+ // noinspection ConstantConditions
579+ return query (preparedStatementCreator , psb , newStreamExtractor (rowMapper ));
580+ }
581+
547582 /*
548583 * (non-Javadoc)
549584 * @see org.springframework.data.cassandra.core.cqlOperations#query(java.lang.String, org.springframework.data.cassandra.core.cql.ResultSetExtractor, java.lang.Object[])
@@ -574,6 +609,16 @@ public <T> List<T> query(String cql, RowMapper<T> rowMapper, Object... args) thr
574609 return query (newPreparedStatementCreator (cql ), newPreparedStatementBinder (args ), newResultSetExtractor (rowMapper ));
575610 }
576611
612+ /*
613+ * (non-Javadoc)
614+ * @see org.springframework.data.cassandra.core.cqlOperations#queryForStream(java.lang.String, org.springframework.data.cassandra.core.cql.RowMapper, java.lang.Object[])
615+ */
616+ @ Override
617+ public <T > Stream <T > queryForStream (String cql , RowMapper <T > rowMapper , Object ... args ) throws DataAccessException {
618+ // noinspection ConstantConditions
619+ return query (newPreparedStatementCreator (cql ), newPreparedStatementBinder (args ), newStreamExtractor (rowMapper ));
620+ }
621+
577622 /*
578623 * (non-Javadoc)
579624 * @see org.springframework.data.cassandra.core.cqlOperations#query(java.lang.String, org.springframework.data.cassandra.core.cql.PreparedStatementBinder, org.springframework.data.cassandra.core.cql.ResultSetExtractor)
@@ -732,8 +777,7 @@ protected PreparedStatementCreator newPreparedStatementCreator(String cql) {
732777 }
733778
734779 /**
735- * Constructs a new instance of the {@link ResultSetExtractor} initialized with and adapting the given
736- * {@link RowCallbackHandler}.
780+ * Constructs a new instance of the {@link ResultSetExtractor} adapting the given {@link RowCallbackHandler}.
737781 *
738782 * @param rowCallbackHandler {@link RowCallbackHandler} to adapt as a {@link ResultSetExtractor}.
739783 * @return a {@link ResultSetExtractor} implementation adapting an instance of the {@link RowCallbackHandler}.
@@ -746,8 +790,7 @@ protected RowCallbackHandlerResultSetExtractor newResultSetExtractor(RowCallback
746790 }
747791
748792 /**
749- * Constructs a new instance of the {@link ResultSetExtractor} initialized with and adapting the given
750- * {@link RowMapper}.
793+ * Constructs a new instance of the {@link ResultSetExtractor} adapting the given {@link RowMapper}.
751794 *
752795 * @param rowMapper {@link RowMapper} to adapt as a {@link ResultSetExtractor}.
753796 * @return a {@link ResultSetExtractor} implementation adapting an instance of the {@link RowMapper}.
@@ -760,8 +803,7 @@ protected <T> RowMapperResultSetExtractor<T> newResultSetExtractor(RowMapper<T>
760803 }
761804
762805 /**
763- * Constructs a new instance of the {@link ResultSetExtractor} initialized with and adapting the given
764- * {@link RowMapper}.
806+ * Constructs a new instance of the {@link ResultSetExtractor} adapting the given {@link RowMapper}.
765807 *
766808 * @param rowMapper {@link RowMapper} to adapt as a {@link ResultSetExtractor}.
767809 * @param rowsExpected number of expected rows in the {@link ResultSet}.
@@ -774,6 +816,19 @@ protected <T> RowMapperResultSetExtractor<T> newResultSetExtractor(RowMapper<T>
774816 return new RowMapperResultSetExtractor <>(rowMapper , rowsExpected );
775817 }
776818
819+ /**
820+ * Constructs a new instance of the {@link ResultSetExtractor} adapting the given {@link RowMapper}.
821+ *
822+ * @param rowMapper {@link RowMapper} to adapt as a {@link ResultSetExtractor}.
823+ * @return a {@link ResultSetExtractor} implementation adapting an instance of the {@link RowMapper}.
824+ * @see ResultSetExtractor
825+ * @see RowCallbackHandler
826+ * @since 3.1
827+ */
828+ protected <T > ResultSetExtractor <Stream <T >> newStreamExtractor (RowMapper <T > rowMapper ) {
829+ return resultSet -> new ResultSetSpliterator <>(resultSet , rowMapper ).stream ();
830+ }
831+
777832 private CqlSession getCurrentSession () {
778833
779834 SessionFactory sessionFactory = getSessionFactory ();
@@ -801,10 +856,79 @@ protected RowCallbackHandlerResultSetExtractor(RowCallbackHandler rowCallbackHan
801856 @ Nullable
802857 public Object extractData (ResultSet resultSet ) {
803858
804- StreamSupport .stream (resultSet .spliterator (), false ).forEach (rowCallbackHandler ::processRow );
805-
859+ resultSet .forEach (rowCallbackHandler ::processRow );
806860 return null ;
807861 }
808862 }
809863
864+ /**
865+ * Spliterator for queryForStream adaptation of a {@link ResultSet} to a {@link Stream}.
866+ *
867+ * @since 3.1
868+ */
869+ private static class ResultSetSpliterator <T > implements Spliterator <T > {
870+
871+ private final Spliterator <Row > delegate ;
872+
873+ private final RowMapper <T > rowMapper ;
874+
875+ private final AtomicInteger counter ;
876+
877+ public ResultSetSpliterator (ResultSet rs , RowMapper <T > rowMapper ) {
878+ this .delegate = rs .spliterator ();
879+ this .rowMapper = rowMapper ;
880+ this .counter = new AtomicInteger ();
881+ }
882+
883+ private ResultSetSpliterator (Spliterator <Row > delegate , RowMapper <T > rowMapper , AtomicInteger counter ) {
884+ this .delegate = delegate ;
885+ this .rowMapper = rowMapper ;
886+ this .counter = counter ;
887+ }
888+
889+ /*
890+ * (non-Javadoc)
891+ * @see java.util.Spliterator#tryAdvance(java.util.function.Consumer)
892+ */
893+ @ Override
894+ public boolean tryAdvance (Consumer <? super T > action ) {
895+ return this .delegate .tryAdvance (row -> action .accept (this .rowMapper .mapRow (row , this .counter .incrementAndGet ())));
896+ }
897+
898+ /*
899+ * (non-Javadoc)
900+ * @see java.util.Spliterator#trySplit()
901+ */
902+ @ Override
903+ @ Nullable
904+ public Spliterator <T > trySplit () {
905+ return new ResultSetSpliterator <>(delegate .trySplit (), this .rowMapper , this .counter );
906+ }
907+
908+ /*
909+ * (non-Javadoc)
910+ * @see java.util.Spliterator#estimateSize()
911+ */
912+ @ Override
913+ public long estimateSize () {
914+ return Long .MAX_VALUE ;
915+ }
916+
917+ /*
918+ * (non-Javadoc)
919+ * @see java.util.Spliterator#characteristics()
920+ */
921+ @ Override
922+ public int characteristics () {
923+ return Spliterator .ORDERED ;
924+ }
925+
926+ /**
927+ * @return
928+ */
929+ public Stream <T > stream () {
930+ return StreamSupport .stream (this , false );
931+ }
932+ }
933+
810934}
0 commit comments