diff --git a/jOOQ/src/main/java/org/jooq/Batch.java b/jOOQ/src/main/java/org/jooq/Batch.java index 97f24909d3..1d95d88367 100644 --- a/jOOQ/src/main/java/org/jooq/Batch.java +++ b/jOOQ/src/main/java/org/jooq/Batch.java @@ -39,6 +39,8 @@ package org.jooq; import java.io.Serializable; import java.sql.Statement; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.Executor; import org.jooq.exception.DataAccessException; @@ -73,6 +75,27 @@ public interface Batch extends Serializable { */ int[] execute() throws DataAccessException; + + + /** + * Execute the batch operation in a new {@link CompletionStage}. + *

+ * The result is asynchronously completed by a task running in an + * {@link Executor} provided by the underlying + * {@link Configuration#executorProvider()}. + * + * @see Statement#executeBatch() + */ + CompletionStage executeAsync(); + + /** + * Execute the query in a new {@link CompletionStage} that is asynchronously + * completed by a task running in the given executor. + */ + CompletionStage executeAsync(Executor executor); + + + /** * Get the number of executed queries in this batch operation */ diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractBatch.java b/jOOQ/src/main/java/org/jooq/impl/AbstractBatch.java new file mode 100644 index 0000000000..8abf73dda0 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractBatch.java @@ -0,0 +1,81 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq.impl; + +import static org.jooq.impl.Tools.blocking; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.Executor; + +import org.jooq.Batch; +import org.jooq.Configuration; +import org.jooq.DSLContext; + +/** + * @author Lukas Eder + */ +abstract class AbstractBatch implements Batch { + + /** + * Generated UID + */ + private static final long serialVersionUID = 5898924458502836002L; + final Configuration configuration; + final DSLContext dsl; + + AbstractBatch(Configuration configuration) { + this.configuration = configuration; + this.dsl = DSL.using(configuration); + } + + + + @Override + public final CompletionStage executeAsync() { + return executeAsync(configuration.executorProvider().provide()); + } + + @Override + public final CompletionStage executeAsync(Executor executor) { + return ExecutorProviderCompletionStage.of(CompletableFuture.supplyAsync(blocking(this::execute), executor), () -> executor); + } + + + +} diff --git a/jOOQ/src/main/java/org/jooq/impl/BatchCRUD.java b/jOOQ/src/main/java/org/jooq/impl/BatchCRUD.java index 4c2ca928de..c56b584215 100644 --- a/jOOQ/src/main/java/org/jooq/impl/BatchCRUD.java +++ b/jOOQ/src/main/java/org/jooq/impl/BatchCRUD.java @@ -46,10 +46,8 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import org.jooq.Batch; import org.jooq.BatchBindStep; import org.jooq.Configuration; -import org.jooq.DSLContext; import org.jooq.ExecuteContext; import org.jooq.Query; import org.jooq.TableRecord; @@ -60,21 +58,19 @@ import org.jooq.exception.DataAccessException; /** * @author Lukas Eder */ -final class BatchCRUD implements Batch { +final class BatchCRUD extends AbstractBatch { /** * Generated UID */ private static final long serialVersionUID = -2935544935267715011L; - private final DSLContext create; - private final Configuration configuration; private final TableRecord[] records; private final Action action; BatchCRUD(Configuration configuration, Action action, TableRecord[] records) { - this.create = DSL.using(configuration); - this.configuration = configuration; + super(configuration); + this.action = action; this.records = records; } @@ -89,12 +85,10 @@ final class BatchCRUD implements Batch { // [#1180] Run batch queries with BatchMultiple, if no bind variables // should be used... - if (executeStaticStatements(configuration.settings())) { + if (executeStaticStatements(configuration.settings())) return executeStatic(); - } - else { + else return executePrepared(); - } } private final int[] executePrepared() { @@ -146,22 +140,19 @@ final class BatchCRUD implements Batch { // The order is preserved as much as possible List result = new ArrayList<>(); for (Entry> entry : queries.entrySet()) { - BatchBindStep batch = create.batch(entry.getValue().get(0)); + BatchBindStep batch = dsl.batch(entry.getValue().get(0)); - for (Query query : entry.getValue()) { + for (Query query : entry.getValue()) batch.bind(query.getBindValues().toArray()); - } int[] array = batch.execute(); - for (int i : array) { + for (int i : array) result.add(i); - } } int[] array = new int[result.size()]; - for (int i = 0; i < result.size(); i++) { + for (int i = 0; i < result.size(); i++) array[i] = result.get(i); - } updateChangedFlag(); return array; @@ -186,9 +177,8 @@ final class BatchCRUD implements Batch { catch (QueryCollectorSignal e) { Query query = e.getQuery(); - if (query.isExecutable()) { + if (query.isExecutable()) queries.add(query); - } } finally { records[i].attach(previous); @@ -196,7 +186,7 @@ final class BatchCRUD implements Batch { } // Resulting statements can be batch executed in their requested order - int[] result = create.batch(queries).execute(); + int[] result = dsl.batch(queries).execute(); updateChangedFlag(); return result; } @@ -227,9 +217,8 @@ final class BatchCRUD implements Batch { // [#3362] If new records (fetched = false) are batch-stored twice in a row, the second // batch-store needs to generate an UPDATE statement. - if (record instanceof AbstractRecord) { + if (record instanceof AbstractRecord) ((AbstractRecord) record).fetched = action != Action.DELETE; - } } } diff --git a/jOOQ/src/main/java/org/jooq/impl/BatchMultiple.java b/jOOQ/src/main/java/org/jooq/impl/BatchMultiple.java index dde84e04b2..876b68f4bc 100644 --- a/jOOQ/src/main/java/org/jooq/impl/BatchMultiple.java +++ b/jOOQ/src/main/java/org/jooq/impl/BatchMultiple.java @@ -40,7 +40,6 @@ package org.jooq.impl; import java.sql.Connection; import java.sql.SQLException; -import org.jooq.Batch; import org.jooq.Configuration; import org.jooq.ExecuteContext; import org.jooq.ExecuteListener; @@ -51,18 +50,18 @@ import org.jooq.exception.ControlFlowSignal; /** * @author Lukas Eder */ -final class BatchMultiple implements Batch { +final class BatchMultiple extends AbstractBatch { /** * Generated UID */ private static final long serialVersionUID = -7337667281292354043L; - private final Configuration configuration; private final Query[] queries; public BatchMultiple(Configuration configuration, Query... queries) { - this.configuration = configuration; + super(configuration); + this.queries = queries; } diff --git a/jOOQ/src/main/java/org/jooq/impl/BatchSingle.java b/jOOQ/src/main/java/org/jooq/impl/BatchSingle.java index 477117a7fa..1f065e16cf 100644 --- a/jOOQ/src/main/java/org/jooq/impl/BatchSingle.java +++ b/jOOQ/src/main/java/org/jooq/impl/BatchSingle.java @@ -54,7 +54,6 @@ import java.util.Map.Entry; import org.jooq.BatchBindStep; import org.jooq.Configuration; -import org.jooq.DSLContext; import org.jooq.DataType; import org.jooq.ExecuteContext; import org.jooq.ExecuteListener; @@ -67,7 +66,7 @@ import org.jooq.tools.JooqLogger; /** * @author Lukas Eder */ -final class BatchSingle implements BatchBindStep { +final class BatchSingle extends AbstractBatch implements BatchBindStep { /** * Generated UID @@ -75,21 +74,19 @@ final class BatchSingle implements BatchBindStep { private static final long serialVersionUID = 3793967258181493207L; private static final JooqLogger log = JooqLogger.getLogger(BatchSingle.class); - private final DSLContext create; - private final Configuration configuration; private final Query query; private final Map> nameToIndexMapping; private final List allBindValues; private final int expectedBindValues; public BatchSingle(Configuration configuration, Query query) { + super(configuration); + int i = 0; ParamCollector collector = new ParamCollector(configuration, false); collector.visit(query); - this.create = DSL.using(configuration); - this.configuration = configuration; this.query = query; this.allBindValues = new ArrayList<>(); this.nameToIndexMapping = new LinkedHashMap<>(); @@ -132,7 +129,7 @@ final class BatchSingle implements BatchBindStep { @SafeVarargs public final BatchSingle bind(Map... namedBindValues) { - List defaultValues = create.extractBindValues(query); + List defaultValues = dsl.extractBindValues(query); Object[][] bindValues = new Object[namedBindValues.length][]; for (int row = 0; row < bindValues.length; row++) { @@ -210,7 +207,7 @@ final class BatchSingle implements BatchBindStep { listener.renderStart(ctx); // [#1520] TODO: Should the number of bind values be checked, here? - ctx.sql(create.render(query)); + ctx.sql(dsl.render(query)); listener.renderEnd(ctx); listener.prepareStart(ctx); @@ -275,9 +272,9 @@ final class BatchSingle implements BatchBindStep { for (int i = 0; i < bindValues.length; i++) query.bind(i + 1, bindValues[i]); - queries.add(create.query(query.getSQL(INLINED))); + queries.add(dsl.query(query.getSQL(INLINED))); } - return create.batch(queries).execute(); + return dsl.batch(queries).execute(); } }