1717
1818import java .util .Collections ;
1919import java .util .List ;
20+ import java .util .concurrent .CompletionStage ;
2021import java .util .function .Consumer ;
2122import java .util .function .Function ;
2223import java .util .stream .Collectors ;
3334import org .springframework .dao .DataAccessException ;
3435import org .springframework .dao .OptimisticLockingFailureException ;
3536import org .springframework .dao .support .DataAccessUtils ;
37+ import org .springframework .dao .support .PersistenceExceptionTranslator ;
3638import org .springframework .data .cassandra .SessionFactory ;
3739import org .springframework .data .cassandra .core .EntityOperations .AdaptibleEntity ;
3840import org .springframework .data .cassandra .core .convert .CassandraConverter ;
@@ -822,6 +824,19 @@ public ListenableFuture<Void> truncate(Class<?> entityClass) {
822824 // Implementation hooks and utility methods
823825 // -------------------------------------------------------------------------
824826
827+ /**
828+ * Create a new statement-based {@link AsyncPreparedStatementHandler} using the statement passed in.
829+ * <p>
830+ * This method allows for the creation to be overridden by subclasses.
831+ *
832+ * @param statement the statement to be prepared.
833+ * @return the new {@link PreparedStatementHandler} to use.
834+ * @since 3.3.3
835+ */
836+ protected AsyncPreparedStatementHandler createPreparedStatementHandler (Statement <?> statement ) {
837+ return new PreparedStatementHandler (statement , exceptionTranslator );
838+ }
839+
825840 private <T > ListenableFuture <EntityWriteResult <T >> executeSave (T entity , CqlIdentifier tableName ,
826841 SimpleStatement statement ) {
827842
@@ -874,7 +889,7 @@ private <T> ListenableFuture<List<T>> doQuery(Statement<?> statement, RowMapper<
874889
875890 if (PreparedStatementDelegate .canPrepare (isUsePreparedStatements (), statement , log )) {
876891
877- PreparedStatementHandler statementHandler = new PreparedStatementHandler (statement );
892+ AsyncPreparedStatementHandler statementHandler = createPreparedStatementHandler (statement );
878893 return getAsyncCqlOperations ().query (statementHandler , statementHandler , rowMapper );
879894 }
880895
@@ -885,7 +900,7 @@ private ListenableFuture<Void> doQuery(Statement<?> statement, RowCallbackHandle
885900
886901 if (PreparedStatementDelegate .canPrepare (isUsePreparedStatements (), statement , log )) {
887902
888- PreparedStatementHandler statementHandler = new PreparedStatementHandler (statement );
903+ AsyncPreparedStatementHandler statementHandler = createPreparedStatementHandler (statement );
889904 return getAsyncCqlOperations ().query (statementHandler , statementHandler , callbackHandler );
890905 }
891906
@@ -900,7 +915,7 @@ private <T> ListenableFuture<T> doExecute(Statement<?> statement, Function<Async
900915
901916 if (PreparedStatementDelegate .canPrepare (isUsePreparedStatements (), statement , log )) {
902917
903- PreparedStatementHandler statementHandler = new PreparedStatementHandler (statement );
918+ AsyncPreparedStatementHandler statementHandler = createPreparedStatementHandler (statement );
904919 return getAsyncCqlOperations ().query (statementHandler , statementHandler ,
905920 (AsyncResultSetExtractor <T >) resultSet -> new AsyncResult <>(mappingFunction .apply (resultSet )));
906921 }
@@ -1021,19 +1036,33 @@ protected T adapt(@Nullable S adapteeResult) {
10211036 }
10221037 }
10231038
1039+ /**
1040+ * General callback interface used to create and bind prepared CQL statements.
1041+ * <p>
1042+ * This interface prepares the CQL statement and sets values on a {@link PreparedStatement} as union-type comprised
1043+ * from {@link AsyncPreparedStatementCreator}, {@link PreparedStatementBinder}, and {@link CqlProvider}.
1044+ *
1045+ * @since 3.3.3
1046+ */
1047+ public interface AsyncPreparedStatementHandler
1048+ extends AsyncPreparedStatementCreator , PreparedStatementBinder , CqlProvider {
1049+
1050+ }
1051+
10241052 /**
10251053 * Utility class to prepare a {@link SimpleStatement} and bind values associated with the statement to a
10261054 * {@link BoundStatement}.
10271055 *
10281056 * @since 3.2
10291057 */
1030- private class PreparedStatementHandler
1031- implements AsyncPreparedStatementCreator , PreparedStatementBinder , CqlProvider {
1058+ public static class PreparedStatementHandler implements AsyncPreparedStatementHandler {
10321059
10331060 private final SimpleStatement statement ;
1061+ private final PersistenceExceptionTranslator exceptionTranslator ;
10341062
1035- public PreparedStatementHandler (Statement <?> statement ) {
1063+ public PreparedStatementHandler (Statement <?> statement , PersistenceExceptionTranslator exceptionTranslator ) {
10361064 this .statement = PreparedStatementDelegate .getStatementForPrepare (statement );
1065+ this .exceptionTranslator = exceptionTranslator ;
10371066 }
10381067
10391068 /*
@@ -1042,7 +1071,17 @@ public PreparedStatementHandler(Statement<?> statement) {
10421071 */
10431072 @ Override
10441073 public ListenableFuture <PreparedStatement > createPreparedStatement (CqlSession session ) throws DriverException {
1045- return new CassandraFutureAdapter <>(session .prepareAsync (statement ), exceptionTranslator );
1074+ return new CassandraFutureAdapter <>(doPrepare (session ), exceptionTranslator );
1075+ }
1076+
1077+ /**
1078+ * Invokes the statement preparation.
1079+ *
1080+ * @param session
1081+ * @return
1082+ */
1083+ protected CompletionStage <PreparedStatement > doPrepare (CqlSession session ) {
1084+ return session .prepareAsync (statement );
10461085 }
10471086
10481087 /*
0 commit comments