From d2123f1c990e12fec76c130f61473a06bcaec45f Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Mon, 12 May 2014 15:14:08 +0200 Subject: [PATCH] [#3229] Add DSLContext.transaction() to implement nested transaction semantics through functional interfaces --- .../test/all/testcases/TransactionTests.java | 4 +- jOOQ/src/main/java/org/jooq/DSLContext.java | 31 ++++++++- .../java/org/jooq/TransactionProvider.java | 3 +- .../java/org/jooq/TransactionalCallable.java | 67 +++++++++++++++++++ .../java/org/jooq/TransactionalRunnable.java | 66 ++++++++++++++++++ .../java/org/jooq/impl/DefaultDSLContext.java | 16 ++++- .../test/java/org/jooq/test/BasicTest.java | 1 - 7 files changed, 179 insertions(+), 9 deletions(-) create mode 100644 jOOQ/src/main/java/org/jooq/TransactionalCallable.java create mode 100644 jOOQ/src/main/java/org/jooq/TransactionalRunnable.java diff --git a/jOOQ-test/src/test/java/org/jooq/test/all/testcases/TransactionTests.java b/jOOQ-test/src/test/java/org/jooq/test/all/testcases/TransactionTests.java index f4365694a0..e8125c8b66 100644 --- a/jOOQ-test/src/test/java/org/jooq/test/all/testcases/TransactionTests.java +++ b/jOOQ-test/src/test/java/org/jooq/test/all/testcases/TransactionTests.java @@ -181,7 +181,7 @@ extends BaseTest { + create.transactionResult(c1 -> { assertAutoCommit(c1.connectionProvider(), false); inserted[0] = @@ -236,7 +236,7 @@ extends BaseTest { + create.transactionResult(c1 -> { assertAutoCommit(c1.connectionProvider(), false); inserted[0] = diff --git a/jOOQ/src/main/java/org/jooq/DSLContext.java b/jOOQ/src/main/java/org/jooq/DSLContext.java index b6db84699b..6f3d757e6f 100644 --- a/jOOQ/src/main/java/org/jooq/DSLContext.java +++ b/jOOQ/src/main/java/org/jooq/DSLContext.java @@ -166,15 +166,40 @@ public interface DSLContext { // ------------------------------------------------------------------------- /** - * Run a {@link Transactional} in the context of this + * Run a {@link TransactionalCallable} in the context of this + * DSLContext's underlying {@link #configuration()}'s + * {@link Configuration#transactionProvider()}, and return the + * transactional's outcome. + *

+ * Both javac and Eclipse compilers contain bugs when overloading methods + * that take both "void-compatible" and "value-compatible" functional + * interfaces: + *

+ * This is why this method was renamed to transactionResult(). + * Future versions of jOOQ may create a better synonym for this, called + * transaction(), which doesn't conflict with + * {@link #transaction(TransactionalRunnable)} + * + * @param transactional The transactional code + * @return The transactional outcome + */ + T transactionResult(TransactionalCallable transactional); + + /** + * Run a {@link TransactionalCallable} in the context of this * DSLContext's underlying {@link #configuration()}'s * {@link Configuration#transactionProvider()}, and return the * transactional's outcome. * * @param transactional The transactional code - * @return The transactional outcome */ - T transaction(Transactional transactional); + void transaction(TransactionalRunnable transactional); // ------------------------------------------------------------------------- // XXX RenderContext and BindContext accessors diff --git a/jOOQ/src/main/java/org/jooq/TransactionProvider.java b/jOOQ/src/main/java/org/jooq/TransactionProvider.java index dfaf8f69a1..8af12cfe9d 100644 --- a/jOOQ/src/main/java/org/jooq/TransactionProvider.java +++ b/jOOQ/src/main/java/org/jooq/TransactionProvider.java @@ -48,7 +48,8 @@ import org.jooq.impl.DefaultTransactionProvider; /** * The TransactionProvider SPI can be used to implement custom * transaction behaviour that is applied when calling - * {@link DSLContext#transaction(Transactional)}. + * {@link DSLContext#transactionResult(TransactionalCallable)} or + * {@link DSLContext#transaction(TransactionalRunnable)}. *

* A new {@link Configuration} copy is created from the calling * {@link DSLContext} for the scope of a single transactions. Implementors may diff --git a/jOOQ/src/main/java/org/jooq/TransactionalCallable.java b/jOOQ/src/main/java/org/jooq/TransactionalCallable.java new file mode 100644 index 0000000000..e1d735a2ef --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/TransactionalCallable.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2009-2014, Data Geekery GmbH (http://www.datageekery.com) + * All rights reserved. + * + * This work is dual-licensed + * - under the Apache Software License 2.0 (the "ASL") + * - under the jOOQ License and Maintenance Agreement (the "jOOQ License") + * ============================================================================= + * You may choose which license applies to you: + * + * - If you're using this work with Open Source databases, you may choose + * either ASL or jOOQ License. + * - If you're using this work with at least one commercial database, you must + * choose jOOQ License + * + * For more information, please visit http://www.jooq.org/licenses + * + * Apache Software License 2.0: + * ----------------------------------------------------------------------------- + * 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. + * + * jOOQ License and Maintenance Agreement: + * ----------------------------------------------------------------------------- + * Data Geekery grants the Customer the non-exclusive, timely limited and + * non-transferable license to install and use the Software under the terms of + * the jOOQ License and Maintenance Agreement. + * + * This library is distributed with a LIMITED WARRANTY. See the jOOQ License + * and Maintenance Agreement for more details: http://www.jooq.org/licensing + */ +package org.jooq; + +/** + * An FunctionalInterface that wraps transactional code. + * + * @author Lukas Eder + */ +public interface TransactionalCallable { + + /** + * Run the transactional code. + *

+ * If this method completes normally, and this is not a nested transaction, + * then the transaction will be committed. If this method completes with an + * exception, then the transaction is rolled back to the beginning of this + * TransactionalCallable. + * + * @param configuration The Configuration in whose context the + * transaction is run. + * @return The outcome of the transaction. + * @throws Exception Any exception that will cause a rollback of the code + * contained in this transaction. If this is a nested + * transaction, the rollback may be performed only to the state + * before executing this TransactionalCallable. + */ + T run(Configuration configuration) throws Exception; +} diff --git a/jOOQ/src/main/java/org/jooq/TransactionalRunnable.java b/jOOQ/src/main/java/org/jooq/TransactionalRunnable.java new file mode 100644 index 0000000000..6061c30e28 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/TransactionalRunnable.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2009-2014, Data Geekery GmbH (http://www.datageekery.com) + * All rights reserved. + * + * This work is dual-licensed + * - under the Apache Software License 2.0 (the "ASL") + * - under the jOOQ License and Maintenance Agreement (the "jOOQ License") + * ============================================================================= + * You may choose which license applies to you: + * + * - If you're using this work with Open Source databases, you may choose + * either ASL or jOOQ License. + * - If you're using this work with at least one commercial database, you must + * choose jOOQ License + * + * For more information, please visit http://www.jooq.org/licenses + * + * Apache Software License 2.0: + * ----------------------------------------------------------------------------- + * 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. + * + * jOOQ License and Maintenance Agreement: + * ----------------------------------------------------------------------------- + * Data Geekery grants the Customer the non-exclusive, timely limited and + * non-transferable license to install and use the Software under the terms of + * the jOOQ License and Maintenance Agreement. + * + * This library is distributed with a LIMITED WARRANTY. See the jOOQ License + * and Maintenance Agreement for more details: http://www.jooq.org/licensing + */ +package org.jooq; + +/** + * An FunctionalInterface that wraps transactional code. + * + * @author Lukas Eder + */ +public interface TransactionalRunnable { + + /** + * Run the transactional code. + *

+ * If this method completes normally, and this is not a nested transaction, + * then the transaction will be committed. If this method completes with an + * exception, then the transaction is rolled back to the beginning of this + * TransactionalRunnable. + * + * @param configuration The Configuration in whose context the + * transaction is run. + * @throws Exception Any exception that will cause a rollback of the code + * contained in this transaction. If this is a nested + * transaction, the rollback may be performed only to the state + * before executing this TransactionalRunnable. + */ + void run(Configuration configuration) throws Exception; +} diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultDSLContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultDSLContext.java index 50126d8002..f458752a93 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultDSLContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultDSLContext.java @@ -181,7 +181,8 @@ import org.jooq.Table; import org.jooq.TableLike; import org.jooq.TableRecord; import org.jooq.TransactionProvider; -import org.jooq.Transactional; +import org.jooq.TransactionalCallable; +import org.jooq.TransactionalRunnable; import org.jooq.TruncateIdentityStep; import org.jooq.UDT; import org.jooq.UDTRecord; @@ -295,7 +296,7 @@ public class DefaultDSLContext implements DSLContext, Serializable { // ------------------------------------------------------------------------- @Override - public T transaction(Transactional transactional) { + public T transactionResult(TransactionalCallable transactional) { T result = null; DefaultTransactionContext ctx = new DefaultTransactionContext(configuration.derive()); @@ -320,6 +321,17 @@ public class DefaultDSLContext implements DSLContext, Serializable { return result; } + @Override + public void transaction(final TransactionalRunnable transactional) { + transactionResult(new TransactionalCallable() { + @Override + public Void run(Configuration c) throws Exception { + transactional.run(c); + return null; + } + }); + } + // ------------------------------------------------------------------------- // XXX RenderContext and BindContext accessors // ------------------------------------------------------------------------- diff --git a/jOOQ/src/test/java/org/jooq/test/BasicTest.java b/jOOQ/src/test/java/org/jooq/test/BasicTest.java index ece065228e..dd81bbf1ee 100644 --- a/jOOQ/src/test/java/org/jooq/test/BasicTest.java +++ b/jOOQ/src/test/java/org/jooq/test/BasicTest.java @@ -63,7 +63,6 @@ import static org.jooq.impl.DSL.replace; import static org.jooq.impl.DSL.round; import static org.jooq.impl.DSL.row; import static org.jooq.impl.DSL.select; -import static org.jooq.impl.DSL.selectOne; import static org.jooq.impl.DSL.sum; import static org.jooq.impl.DSL.tableByName; import static org.jooq.impl.DSL.trueCondition;