Firebird Documentation IndexFirebird 3.0 Developer's GuideCreating an Application with jOOQ and Spring MVC → Working with Transactions
Firebird Home Firebird Home Prev: Creating SQL Queries Using jOOQFirebird Documentation IndexUp: Creating an Application with jOOQ and Spring MVCNext: Writing the Application Code

Working with Transactions

Table of Contents

Explicit Transactions

By default, jOOQ runs in a mode that commits transactions automatically. It starts a new transaction for each SQL statement and commits the transaction if there are no errors in the execution of the statement. The transaction is rolled back if an error occurs.

The default transaction has the following parameters: READ_WRITE | READ_COMMITTED | REC_VERSION | WAIT, the same parameters that are used by the JDBC driver. You can change the default isolation mode using the parameters of the connection pool—see BasicDataSource.setDefaultTransactionIsolation in the getDataSource method of the JooqConfig configuration class.

Explicit Transactions

Table of Contents

Transaction Parameters

In jOOQ you have several ways to control transactions explicitly. Since we are going to develop our application using the Spring Framework, we will use the transaction manager specified in the configuration (JooqConfig). You can get the transaction manager by declaring the txMgr property in the class as follows:

@Autowired 
private DataSourceTransactionManager txMgr;  
        

The standard scenario for using this technique with a transaction would be coded like this:

TransactionStatus tx = txMgr.getTransaction(new DefaultTransactionDefinition());
try {
    // actions in the context of a transaction
    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();
    // transaction commit
    txMgr.commit(tx);
}
catch (DataAccessException e) {
    // transaction rollback
    txMgr.rolback(tx);
}
        

However, Spring enables that scenario to be implemented much more easily using the @Transactional annotation specified before the method of the class. Thereby, all actions performed by the method will be wrapped in the transaction.

    /**
     * Delete customer
     *
     * @param customerId
     */
    @Transactional(propagation = Propagation.REQUIRED,
                   isolation = Isolation.REPEATABLE_READ)
    public void delete(int customerId) {
        this.dsl.deleteFrom(CUSTOMER)
                .where(CUSTOMER.CUSTOMER_ID.eq(customerId))
                .execute();
    }
        

Transaction Parameters

Propagation

The propagation parameter defines how to work with transactions if our method is called from an external transaction.

  • Propagation.REQUIRED—execute in the existing transaction if there is one. Otherwise, create a new one.
  • Propagation.MANDATORY—execute in the existing transaction if there is one. Otherwise, raise an exception.
  • Propagation.SUPPORTS—execute in the existing transaction if there is one. Otherwise, execute outside the transaction.
  • Propagation.NOT_SUPPORTED—always execute outside the transaction. If there is an existing one, it will be suspended.
  • Propagation.REQUIRES_NEW—always execute in a new independent transaction. If there is an existing one, it will be suspended until the new transaction is ended.
  • Propagation.NESTED—if there is an existing transaction, execute in a new so-called “nested” transaction. If the nested transaction is rolled back, it will not affect the external transaction; if the external transaction is rolled back, the nested one will be rolled back as well. If there is no existing transaction, a new one is simply created.
  • Propagation.NEVER—always execute outside the transaction. Raise an exception if there is an existing one.

Isolation Level

The isolation parameter defines the isolation level. Five values are supported: DEFAULT, READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE. If the DEFAULT value of the isolation parameter is specified, that level will be used.

The other isolation levels are taken from the SQL standard, not all of them supported exactly by Firebird. Only the READ_COMMITED level corresponds in all of the criteria, so JDBC READ_COMMITTED is mapped into read_committed in Firebird. REPEATABLE_READ is mapped into concurrency (SNAPSHOT) and SERIALIZABLE is mapped into consistency (SNAPSHOT TABLE STABILITY).

Firebird supports additional transaction parameters besides isolation level, viz. NO RECORD_VERSION/RECORD_VERSION (applicable only to a transaction with READ COMMITTED isolation) and WAIT/NO WAIT. The standard isolation levels can be mapped to Firebird transaction parameters by specifying the properties of the JDBC connection (see more details in the Using Transactions chapter of Jaybird 2.1 JDBC driver Java Programmer's Manual.

If your transaction works with more than one query, it is recommended to use the REPEATABLE_READ isolation level to maintain data consistency.

Read Mode
By default, a transaction is in the read-write mode. The readOnly property in the @Transactional annotation can be used to specify that it is to be read-only.
Prev: Creating SQL Queries Using jOOQFirebird Documentation IndexUp: Creating an Application with jOOQ and Spring MVCNext: Writing the Application Code
Firebird Documentation IndexFirebird 3.0 Developer's GuideCreating an Application with jOOQ and Spring MVC → Working with Transactions