|
46 | 46 | import org.apache.commons.logging.LogFactory;
|
47 | 47 | import org.reactivestreams.Publisher;
|
48 | 48 | import org.springframework.dao.DataAccessException;
|
49 |
| -import org.springframework.dao.IncorrectResultSizeDataAccessException; |
50 | 49 | import org.springframework.dao.UncategorizedDataAccessException;
|
51 | 50 | import org.springframework.data.jdbc.core.function.connectionfactory.ConnectionProxy;
|
52 | 51 | import org.springframework.data.util.Pair;
|
|
60 | 59 | *
|
61 | 60 | * @author Mark Paluch
|
62 | 61 | */
|
63 |
| -class DefaultDatabaseClient implements DatabaseClient { |
| 62 | +class DefaultDatabaseClient implements DatabaseClient, ConnectionAccessor { |
64 | 63 |
|
65 | 64 | /** Logger available to subclasses */
|
66 | 65 | protected final Log logger = LogFactory.getLog(getClass());
|
@@ -104,54 +103,56 @@ public InsertIntoSpec insert() {
|
104 | 103 |
|
105 | 104 | /**
|
106 | 105 | * Execute a callback {@link Function} within a {@link Connection} scope. The function is responsible for creating a
|
107 |
| - * {@link Flux}. The connection is released after the {@link Flux} terminates (or the subscription is cancelled). |
| 106 | + * {@link Mono}. The connection is released after the {@link Mono} terminates (or the subscription is cancelled). |
108 | 107 | * Connection resources must not be passed outside of the {@link Function} closure, otherwise resources may get
|
109 | 108 | * defunct.
|
110 | 109 | *
|
111 | 110 | * @param action must not be {@literal null}.
|
112 |
| - * @return the resulting {@link Flux}. |
| 111 | + * @return the resulting {@link Mono}. |
113 | 112 | * @throws DataAccessException
|
114 | 113 | */
|
115 |
| - public <T> Flux<T> executeMany(Function<Connection, Flux<T>> action) throws DataAccessException { |
| 114 | + @Override |
| 115 | + public <T> Mono<T> inConnection(Function<Connection, Mono<T>> action) throws DataAccessException { |
116 | 116 |
|
117 | 117 | Assert.notNull(action, "Callback object must not be null");
|
118 | 118 |
|
119 | 119 | Mono<Connection> connectionMono = getConnection();
|
120 | 120 | // Create close-suppressing Connection proxy, also preparing returned Statements.
|
121 | 121 |
|
122 |
| - return Flux.usingWhen(connectionMono, it -> { |
| 122 | + return Mono.usingWhen(connectionMono, it -> { |
123 | 123 |
|
124 | 124 | Connection connectionToUse = createConnectionProxy(it);
|
125 | 125 |
|
126 |
| - return doInConnectionMany(connectionToUse, action); |
| 126 | + return doInConnection(connectionToUse, action); |
127 | 127 | }, this::closeConnection, this::closeConnection, this::closeConnection) //
|
128 |
| - .onErrorMap(SQLException.class, ex -> translateException("executeMany", getSql(action), ex)); |
| 128 | + .onErrorMap(SQLException.class, ex -> translateException("execute", getSql(action), ex)); |
129 | 129 | }
|
130 | 130 |
|
131 | 131 | /**
|
132 | 132 | * Execute a callback {@link Function} within a {@link Connection} scope. The function is responsible for creating a
|
133 |
| - * {@link Mono}. The connection is released after the {@link Mono} terminates (or the subscription is cancelled). |
| 133 | + * {@link Flux}. The connection is released after the {@link Flux} terminates (or the subscription is cancelled). |
134 | 134 | * Connection resources must not be passed outside of the {@link Function} closure, otherwise resources may get
|
135 | 135 | * defunct.
|
136 | 136 | *
|
137 | 137 | * @param action must not be {@literal null}.
|
138 |
| - * @return the resulting {@link Mono}. |
| 138 | + * @return the resulting {@link Flux}. |
139 | 139 | * @throws DataAccessException
|
140 | 140 | */
|
141 |
| - public <T> Mono<T> execute(Function<Connection, Mono<T>> action) throws DataAccessException { |
| 141 | + @Override |
| 142 | + public <T> Flux<T> inConnectionMany(Function<Connection, Flux<T>> action) throws DataAccessException { |
142 | 143 |
|
143 | 144 | Assert.notNull(action, "Callback object must not be null");
|
144 | 145 |
|
145 | 146 | Mono<Connection> connectionMono = getConnection();
|
146 | 147 | // Create close-suppressing Connection proxy, also preparing returned Statements.
|
147 | 148 |
|
148 |
| - return Mono.usingWhen(connectionMono, it -> { |
| 149 | + return Flux.usingWhen(connectionMono, it -> { |
149 | 150 |
|
150 | 151 | Connection connectionToUse = createConnectionProxy(it);
|
151 | 152 |
|
152 |
| - return doInConnection(connectionToUse, action); |
| 153 | + return doInConnectionMany(connectionToUse, action); |
153 | 154 | }, this::closeConnection, this::closeConnection, this::closeConnection) //
|
154 |
| - .onErrorMap(SQLException.class, ex -> translateException("execute", getSql(action), ex)); |
| 155 | + .onErrorMap(SQLException.class, ex -> translateException("executeMany", getSql(action), ex)); |
155 | 156 | }
|
156 | 157 |
|
157 | 158 | /**
|
@@ -292,7 +293,8 @@ protected <T> SqlResult<T> exchange(String sql, BiFunction<Row, RowMetadata, T>
|
292 | 293 |
|
293 | 294 | Function<Connection, Flux<Result>> resultFunction = it -> Flux.from(executeFunction.apply(it).execute());
|
294 | 295 |
|
295 |
| - return new DefaultSqlResultFunctions<>(sql, // |
| 296 | + return new DefaultSqlResult<>(DefaultDatabaseClient.this, // |
| 297 | + sql, // |
296 | 298 | resultFunction, //
|
297 | 299 | it -> resultFunction.apply(it).flatMap(Result::getRowsUpdated).next(), //
|
298 | 300 | mappingFunction);
|
@@ -564,7 +566,8 @@ private <T> SqlResult<T> exchange(BiFunction<Row, RowMetadata, T> mappingFunctio
|
564 | 566 | Function<Connection, Flux<Result>> resultFunction = it -> Flux
|
565 | 567 | .from(insertFunction.apply(it).executeReturningGeneratedKeys());
|
566 | 568 |
|
567 |
| - return new DefaultSqlResultFunctions<>(sql, // |
| 569 | + return new DefaultSqlResult<>(DefaultDatabaseClient.this, // |
| 570 | + sql, // |
568 | 571 | resultFunction, //
|
569 | 572 | it -> resultFunction.apply(it).flatMap(Result::getRowsUpdated).next(), //
|
570 | 573 | mappingFunction);
|
@@ -680,102 +683,14 @@ private <R> SqlResult<R> exchange(Object toInsert, BiFunction<Row, RowMetadata,
|
680 | 683 | Function<Connection, Flux<Result>> resultFunction = it -> Flux
|
681 | 684 | .from(insertFunction.apply(it).executeReturningGeneratedKeys());
|
682 | 685 |
|
683 |
| - return new DefaultSqlResultFunctions<>(sql, // |
| 686 | + return new DefaultSqlResult<>(DefaultDatabaseClient.this, // |
| 687 | + sql, // |
684 | 688 | resultFunction, //
|
685 | 689 | it -> resultFunction.apply(it).flatMap(Result::getRowsUpdated).next(), //
|
686 | 690 | mappingFunction);
|
687 | 691 | }
|
688 | 692 | }
|
689 | 693 |
|
690 |
| - /** |
691 |
| - * Default {@link org.springframework.data.jdbc.core.function.SqlResult} implementation. |
692 |
| - */ |
693 |
| - class DefaultSqlResultFunctions<T> implements SqlResult<T> { |
694 |
| - |
695 |
| - private final String sql; |
696 |
| - private final Function<Connection, Flux<Result>> resultFunction; |
697 |
| - private final Function<Connection, Mono<Integer>> updatedRowsFunction; |
698 |
| - private final FetchSpec<T> fetchSpec; |
699 |
| - |
700 |
| - DefaultSqlResultFunctions(String sql, Function<Connection, Flux<Result>> resultFunction, |
701 |
| - Function<Connection, Mono<Integer>> updatedRowsFunction, BiFunction<Row, RowMetadata, T> mappingFunction) { |
702 |
| - |
703 |
| - this.sql = sql; |
704 |
| - this.resultFunction = resultFunction; |
705 |
| - this.updatedRowsFunction = updatedRowsFunction; |
706 |
| - |
707 |
| - this.fetchSpec = new DefaultFetchFunctions<>(sql, |
708 |
| - it -> resultFunction.apply(it).flatMap(result -> result.map(mappingFunction)), updatedRowsFunction); |
709 |
| - } |
710 |
| - |
711 |
| - @Override |
712 |
| - public <R> SqlResult<R> extract(BiFunction<Row, RowMetadata, R> mappingFunction) { |
713 |
| - return new DefaultSqlResultFunctions<>(sql, resultFunction, updatedRowsFunction, mappingFunction); |
714 |
| - } |
715 |
| - |
716 |
| - @Override |
717 |
| - public Mono<T> one() { |
718 |
| - return fetchSpec.one(); |
719 |
| - } |
720 |
| - |
721 |
| - @Override |
722 |
| - public Mono<T> first() { |
723 |
| - return fetchSpec.first(); |
724 |
| - } |
725 |
| - |
726 |
| - @Override |
727 |
| - public Flux<T> all() { |
728 |
| - return fetchSpec.all(); |
729 |
| - } |
730 |
| - |
731 |
| - @Override |
732 |
| - public Mono<Integer> rowsUpdated() { |
733 |
| - return fetchSpec.rowsUpdated(); |
734 |
| - } |
735 |
| - } |
736 |
| - |
737 |
| - @RequiredArgsConstructor |
738 |
| - class DefaultFetchFunctions<T> implements FetchSpec<T> { |
739 |
| - |
740 |
| - private final String sql; |
741 |
| - private final Function<Connection, Flux<T>> resultFunction; |
742 |
| - private final Function<Connection, Mono<Integer>> updatedRowsFunction; |
743 |
| - |
744 |
| - @Override |
745 |
| - public Mono<T> one() { |
746 |
| - |
747 |
| - return all().buffer(2) // |
748 |
| - .flatMap(it -> { |
749 |
| - |
750 |
| - if (it.isEmpty()) { |
751 |
| - return Mono.empty(); |
752 |
| - } |
753 |
| - |
754 |
| - if (it.size() > 1) { |
755 |
| - return Mono.error(new IncorrectResultSizeDataAccessException( |
756 |
| - String.format("Query [%s] returned non unique result.", this.sql), 1)); |
757 |
| - } |
758 |
| - |
759 |
| - return Mono.just(it.get(0)); |
760 |
| - }).next(); |
761 |
| - } |
762 |
| - |
763 |
| - @Override |
764 |
| - public Mono<T> first() { |
765 |
| - return all().next(); |
766 |
| - } |
767 |
| - |
768 |
| - @Override |
769 |
| - public Flux<T> all() { |
770 |
| - return executeMany(resultFunction); |
771 |
| - } |
772 |
| - |
773 |
| - @Override |
774 |
| - public Mono<Integer> rowsUpdated() { |
775 |
| - return execute(updatedRowsFunction); |
776 |
| - } |
777 |
| - } |
778 |
| - |
779 | 694 | private static <T> Flux<T> doInConnectionMany(Connection connection, Function<Connection, Flux<T>> action) {
|
780 | 695 |
|
781 | 696 | try {
|
|
0 commit comments