[#3229] Added examples using binding Spring's TransactionManager to
jOOQ's new transaction() API
This commit is contained in:
parent
b901f0e954
commit
03b4797a45
@ -19,7 +19,7 @@
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" path="target/generated-sources/jooq-h2"/>
|
||||
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
|
||||
@ -5,9 +5,9 @@ org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annota
|
||||
org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
|
||||
org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
@ -106,7 +106,7 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disa
|
||||
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
|
||||
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
||||
org.eclipse.jdt.core.formatter.align_type_members_on_columns=true
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=48
|
||||
@ -191,7 +191,6 @@ org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
|
||||
org.eclipse.jdt.core.formatter.indentation.size=4
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
|
||||
|
||||
@ -97,6 +97,26 @@
|
||||
</resources>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.3.2</version>
|
||||
<configuration>
|
||||
<fork>true</fork>
|
||||
<maxmem>1024m</maxmem>
|
||||
<meminitial>256m</meminitial>
|
||||
<encoding>UTF-8</encoding>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<debug>true</debug>
|
||||
<debuglevel>lines,vars,source</debuglevel>
|
||||
<compilerArguments>
|
||||
<!-- [#2413] Make compiler warnings a bit more visible
|
||||
But don't fail (yet) -->
|
||||
<Xlint:-varargs/>
|
||||
</compilerArguments>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- We're using the properties plugin to load external properties into Maven.
|
||||
See this excellent blog post for an explanation:
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2013, 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.example.spring;
|
||||
|
||||
import org.jooq.Transaction;
|
||||
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
|
||||
public class SpringTransaction implements Transaction {
|
||||
public final TransactionStatus tx;
|
||||
|
||||
public SpringTransaction(TransactionStatus tx) {
|
||||
this.tx = tx;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2013, 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.example.spring;
|
||||
|
||||
import static org.springframework.transaction.TransactionDefinition.PROPAGATION_NESTED;
|
||||
|
||||
import org.jooq.TransactionContext;
|
||||
import org.jooq.TransactionProvider;
|
||||
import org.jooq.tools.JooqLogger;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
|
||||
/**
|
||||
* An example <code>TransactionProvider</code> implementing the
|
||||
* {@link TransactionProvider} contract for use with Spring.
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public class SpringTransactionProvider implements TransactionProvider {
|
||||
|
||||
private static final JooqLogger log = JooqLogger.getLogger(SpringTransactionProvider.class);
|
||||
|
||||
@Autowired
|
||||
DataSourceTransactionManager txMgr;
|
||||
|
||||
@Override
|
||||
public void begin(TransactionContext ctx) {
|
||||
log.info("Begin transaction");
|
||||
|
||||
// This TransactionProvider behaves like jOOQ's DefaultTransactionProvider,
|
||||
// which supports nested transactions using Savepoints
|
||||
TransactionStatus tx = txMgr.getTransaction(new DefaultTransactionDefinition(PROPAGATION_NESTED));
|
||||
ctx.transaction(new SpringTransaction(tx));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit(TransactionContext ctx) {
|
||||
log.info("commit transaction");
|
||||
|
||||
txMgr.commit(((SpringTransaction) ctx.transaction()).tx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollback(TransactionContext ctx) {
|
||||
log.info("rollback transaction");
|
||||
|
||||
txMgr.rollback(((SpringTransaction) ctx.transaction()).tx);
|
||||
}
|
||||
}
|
||||
@ -23,6 +23,11 @@
|
||||
<property name="dataSource" ref="dataSource" />
|
||||
</bean>
|
||||
|
||||
<!-- Configure jOOQ's TransactionProvider as a proxy to Spring's transaction manager -->
|
||||
<bean id="transactionProvider"
|
||||
class="org.jooq.example.spring.SpringTransactionProvider">
|
||||
</bean>
|
||||
|
||||
<!-- Configure jOOQ's ConnectionProvider to use Spring's TransactionAwareDataSourceProxy,
|
||||
which can dynamically discover the transaction context -->
|
||||
<bean id="transactionAwareDataSource"
|
||||
@ -45,19 +50,20 @@
|
||||
Implement your own Configuration for more reliable behaviour -->
|
||||
<bean class="org.jooq.impl.DefaultConfiguration" name="config">
|
||||
<constructor-arg index="0" ref="connectionProvider" />
|
||||
<constructor-arg index="1"><null /></constructor-arg>
|
||||
<constructor-arg index="1" ref="transactionProvider" />
|
||||
<constructor-arg index="2"><null /></constructor-arg>
|
||||
<constructor-arg index="3">
|
||||
<constructor-arg index="3"><null /></constructor-arg>
|
||||
<constructor-arg index="4">
|
||||
<list>
|
||||
<bean class="org.jooq.impl.DefaultExecuteListenerProvider">
|
||||
<constructor-arg index="0" ref="exceptionTranslator"/>
|
||||
</bean>
|
||||
</list>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="4"><null /></constructor-arg>
|
||||
<constructor-arg index="5"><value type="org.jooq.SQLDialect">H2</value></constructor-arg>
|
||||
<constructor-arg index="6"><null /></constructor-arg>
|
||||
<constructor-arg index="5"><null /></constructor-arg>
|
||||
<constructor-arg index="6"><value type="org.jooq.SQLDialect">H2</value></constructor-arg>
|
||||
<constructor-arg index="7"><null /></constructor-arg>
|
||||
<constructor-arg index="8"><null /></constructor-arg>
|
||||
</bean>
|
||||
|
||||
<!-- This is the "business-logic" -->
|
||||
|
||||
@ -44,8 +44,11 @@ import static org.jooq.example.db.h2.Tables.BOOK;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.example.spring.BookService;
|
||||
import org.jooq.example.spring.SpringTransactionProvider;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
@ -74,6 +77,7 @@ public class TransactionTest {
|
||||
|
||||
@Autowired DSLContext dsl;
|
||||
@Autowired DataSourceTransactionManager txMgr;
|
||||
@Autowired SpringTransactionProvider txProvider;
|
||||
@Autowired BookService books;
|
||||
|
||||
@After
|
||||
@ -127,4 +131,92 @@ public class TransactionTest {
|
||||
assertEquals(4, dsl.fetchCount(BOOK));
|
||||
assertTrue(rollback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testjOOQTransactionsSimple() {
|
||||
boolean rollback = false;
|
||||
|
||||
try {
|
||||
dsl.transaction(c -> {
|
||||
|
||||
// This is a "bug". The same book is created twice, resulting in a
|
||||
// constraint violation exception
|
||||
for (int i = 0; i < 2; i++)
|
||||
dsl.insertInto(BOOK)
|
||||
.set(BOOK.ID, 5)
|
||||
.set(BOOK.AUTHOR_ID, 1)
|
||||
.set(BOOK.TITLE, "Book 5")
|
||||
.execute();
|
||||
|
||||
Assert.fail();
|
||||
});
|
||||
}
|
||||
|
||||
// Upon the constraint violation, the transaction must already have been rolled back
|
||||
catch (DataAccessException e) {
|
||||
rollback = true;
|
||||
}
|
||||
|
||||
assertEquals(4, dsl.fetchCount(BOOK));
|
||||
assertTrue(rollback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testjOOQTransactionsNested() {
|
||||
AtomicBoolean rollback1 = new AtomicBoolean(false);
|
||||
AtomicBoolean rollback2 = new AtomicBoolean(false);
|
||||
|
||||
try {
|
||||
|
||||
// If using Spring transactions, we don't need the c1 reference
|
||||
dsl.transaction(c1 -> {
|
||||
|
||||
// The first insertion will work
|
||||
dsl.insertInto(BOOK)
|
||||
.set(BOOK.ID, 5)
|
||||
.set(BOOK.AUTHOR_ID, 1)
|
||||
.set(BOOK.TITLE, "Book 5")
|
||||
.execute();
|
||||
|
||||
assertEquals(5, dsl.fetchCount(BOOK));
|
||||
|
||||
try {
|
||||
|
||||
// Nest transactions using Spring. This should create a savepoint, right here
|
||||
// If using Spring transactions, we don't need the c2 reference
|
||||
dsl.transaction(c2 -> {
|
||||
|
||||
// The second insertion shouldn't work
|
||||
for (int i = 0; i < 2; i++)
|
||||
dsl.insertInto(BOOK)
|
||||
.set(BOOK.ID, 6)
|
||||
.set(BOOK.AUTHOR_ID, 1)
|
||||
.set(BOOK.TITLE, "Book 6")
|
||||
.execute();
|
||||
|
||||
Assert.fail();
|
||||
});
|
||||
}
|
||||
|
||||
catch (DataAccessException e) {
|
||||
rollback1.set(true);
|
||||
}
|
||||
|
||||
// We should've rolled back to the savepoint
|
||||
assertEquals(5, dsl.fetchCount(BOOK));
|
||||
|
||||
throw new org.jooq.exception.DataAccessException("Rollback");
|
||||
});
|
||||
}
|
||||
|
||||
// Upon the constraint violation, the transaction must already have been rolled back
|
||||
catch (org.jooq.exception.DataAccessException e) {
|
||||
assertEquals("Rollback", e.getMessage());
|
||||
rollback2.set(true);
|
||||
}
|
||||
|
||||
assertEquals(4, dsl.fetchCount(BOOK));
|
||||
assertTrue(rollback2.get());
|
||||
assertTrue(rollback2.get());
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user