Share jOOQ on Facebook
Share jOOQ on Twitter

All versions: 3.9 | 3.8 | 3.7 | 3.6 | 3.5 | 3.4 | 3.3 | Development versions: 3.10 | Unsupported versions: 3.2 | 3.1 | 3.0 | 2.6 | 2.5

jOOQ and Spring are easy to integrate. In this example, we shall integrate:

Before you copy the manual examples, consider also these further resources:

Add the required Maven dependencies

For this example, we'll create the following Maven dependencies

<!-- Use this or the latest Spring RELEASE version -->


    <!-- Database access -->
        <!-- Use org.jooq            for the Open Source Edition
               for commercial editions, 
        for commercial editions with Java 6 support,
                 org.jooq.trial      for the free trial edition 
             Note: Only the Open Source Edition is hosted on Maven Central. 
                   Import the others manually from your distribution -->

    <!-- Logging -->

    <!-- Spring (transitive dependencies are not listed explicitly) -->

    <!-- Testing -->

Note that only the jOOQ Open Source Edition is available from Maven Central. If you're using the jOOQ Professional Edition or the jOOQ Enterprise Edition, you will have to manually install jOOQ in your local Nexus, or in your local Maven cache. For more information, please refer to the licensing pages.

Create a minimal Spring configuration file

The above dependencies are configured together using a Spring Beans configuration:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns=""

    <!-- This is needed if you want to use the @Transactional annotation -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close" >
        <!-- These properties are replaced by Maven "resources" -->
       <property name="url" value="${db.url}" />
       <property name="driverClassName" value="${db.driver}" />
       <property name="username" value="${db.username}" />
       <property name="password" value="${db.password}" />

    <!-- Configure Spring's transaction manager to use a DataSource -->
    <bean id="transactionManager"
        <property name="dataSource" ref="dataSource" />

    <!-- Configure jOOQ's ConnectionProvider to use Spring's TransactionAwareDataSourceProxy,
         which can dynamically discover the transaction context -->
    <bean id="transactionAwareDataSource"
        <constructor-arg ref="dataSource" />

    <bean class="org.jooq.impl.DataSourceConnectionProvider" name="connectionProvider">
        <constructor-arg ref="transactionAwareDataSource" />

    <!-- Configure the DSL object, optionally overriding jOOQ Exceptions with Spring Exceptions -->
    <bean id="dsl" class="org.jooq.impl.DefaultDSLContext">
        <constructor-arg ref="config" />
    <bean id="exceptionTranslator" class="org.jooq.example.spring.exception.ExceptionTranslator" />
    <!-- Invoking an internal, package-private constructor for the example
         Implement your own Configuration for more reliable behaviour -->
    <bean class="org.jooq.impl.DefaultConfiguration" name="config">
        <property name="SQLDialect"><value type="org.jooq.SQLDialect">H2</value></property>
        <property name="connectionProvider" ref="connectionProvider" />
        <property name="executeListenerProvider">
                <bean class="org.jooq.impl.DefaultExecuteListenerProvider">
                    <constructor-arg index="0" ref="exceptionTranslator"/>
    <!-- This is the "business-logic" -->
    <bean id="books" class="org.jooq.example.spring.impl.DefaultBookService"/>

Run a query using the above configuration:

With the above configuration, you should be ready to run queries pretty quickly. For instance, in an integration-test, you could use Spring to run JUnit:

@ContextConfiguration(locations = {"/jooq-spring.xml"})
public class QueryTest {

    DSLContext create;

    public void testJoin() throws Exception {
        // All of these tables were generated by jOOQ's Maven plugin
        Book b ="b");
        Author a ="a");
        BookStore s ="s");
        BookToBookStore t ="t");

        Result<Record3<String, String, Integer>> result =, a.LAST_NAME, countDistinct(s.NAME))
              .groupBy(a.FIRST_NAME, a.LAST_NAME)

        assertEquals(2, result.size());
        assertEquals("Paulo", result.getValue(0, a.FIRST_NAME));
        assertEquals("George", result.getValue(1, a.FIRST_NAME));

        assertEquals("Coelho", result.getValue(0, a.LAST_NAME));
        assertEquals("Orwell", result.getValue(1, a.LAST_NAME));

        assertEquals(Integer.valueOf(3), result.getValue(0, countDistinct(s.NAME)));
        assertEquals(Integer.valueOf(2), result.getValue(1, countDistinct(s.NAME)));

Run a queries in an explicit transaction:

The following example shows how you can use Spring's TransactionManager to explicitly handle transactions:

@ContextConfiguration(locations = {"/jooq-spring.xml"})
public class TransactionTest {

    @Autowired DSLContext                   dsl;
    @Autowired DataSourceTransactionManager txMgr;
    @Autowired BookService                  books;

    public void teardown() {

        // Delete all books that were created in any test

    public void testExplicitTransactions() {
        boolean rollback = false;

        TransactionStatus tx = txMgr.getTransaction(new DefaultTransactionDefinition());
        try {

            // This is a "bug". The same book is created twice, resulting in a
            // constraint violation exception
            for (int i = 0; i < 2; i++)
                   .set(BOOK.ID, 5)
                   .set(BOOK.AUTHOR_ID, 1)
                   .set(BOOK.TITLE, "Book 5")

        // Upon the constraint violation, we explicitly roll back the transaction.
        catch (DataAccessException e) {
            rollback = true;

        assertEquals(4, dsl.fetchCount(BOOK));

Run queries using declarative transactions

Spring-TX has very powerful means to handle transactions declaratively, using the @Transactional annotation. The BookService that we had defined in the previous Spring configuration can be seen here:

public interface BookService {

     * Create a new book.
     * <p>
     * The implementation of this method has a bug, which causes this method to
     * fail and roll back the transaction.
    void create(int id, int authorId, String title);


And here is how we interact with it:

    public void testDeclarativeTransactions() {
        boolean rollback = false;

        try {
            // The service has a "bug", resulting in a constraint violation exception
            books.create(5, 1, "Book 5");
        catch (DataAccessException ignore) {
            rollback = true;

        assertEquals(4, dsl.fetchCount(BOOK));

Run queries using jOOQ's transaction API

jOOQ has its own programmatic transaction API that can be used with Spring transactions by implementing the jOOQ org.jooq.TransactionProvider SPI and passing that to your jOOQ Configuration. More details about this transaction API can be found in the manual's section about transaction management.

You can try the above example yourself by downloading it from GitHub.

The jOOQ Logo