Version v1.15 of the documentation is no longer actively maintained. The site that you are currently viewing is an archived snapshot. For up-to-date documentation, see the latest version.

Transaction

Overview

Komapper provides a High-level API for transaction management.

Transaction control

The API for transaction control provided by Komapper differs between the JDBC and R2DBC versions, but the visual interface is unified. The following explanation assumes that JdbcDatabase or R2dbcDatabase is declared with the variable db as shown below.

val db = JdbcDatabase("jdbc:h2:mem:example;DB_CLOSE_DELAY=-1")
val db = R2dbcDatabase("r2dbc:h2:mem:///example;DB_CLOSE_DELAY=-1")

Beginning and ending transactions

A transaction can be begun by calling the withTransaction function:

db.withTransaction {
    ..
}

The withTransaction function accepts a transaction attribute and a transaction property`:

db.withTransaction(
  transactionAttribute = TransactionAttribute.REQUIRES_NEW, 
  transactionProperty = TransactionProperty.IsolationLevel.SERIALIZABLE) {
    ..
}

The transaction attribute can be one of the following two types:

REQUIRED
Support a current transaction; create a new one if none exists.
REQUIRES_NEW
Create a new transaction, suspending the current transaction if one exists.

The transaction property can contain various property elements:

IsolationLevel
Isolation level requested for the transaction.
LockWaitTime
Lock wait timeout.
Name
Name of the transaction.
ReadOnly
Whether the transaction should be started in read-only mode.

Multiple transaction property elements can be combined into a single transaction property with the + operator:

val property = TransactionProperty.IsolationLevel.SERIALIZABLE + TransactionProperty.Name("myTx") + TransactionProperty.ReadOnly(true)

The transaction is committed or rolled back when the call to the withTransaction function is finished.

The conditions for rollback are as follows:

  • Call to the withTransaction function is terminated with an exception.
  • Explicit rollback is indicated in withTransaction function.

If the above rollback conditions are not met, the commit is performed.

Explicit rollback

If the setRollbackOnly function is called, rollback is performed at the end of the withTransaction function:

db.withTransaction { tx ->
    ..
    tx.setRollbackOnly()
    ..
}

You can check if you have already called the setRollbackOnly function with the isRollbackOnly function:

db.withTransaction { tx ->
    ..
    if (tx.isRollbackOnly()) {
        ..
    }
    ..
}

Beginning and ending new transactions

To begin a new transaction when the current transaction exists, call the requiresNew function.

db.withTransaction { tx ->
    ..
    tx.requiresNew {
        ..
    }
    ..
}

The requiresNew function accepts a transaction property`:

db.withTransaction { tx ->
    ..
    tx.requiresNew(transactionProperty = TransactionProperty.IsolationLevel.SERIALIZABLE) {
        ..
    }
    ..
}

The transaction is committed or rolled back when the call to the requiresNew function is finished.

The conditions for rollback are as follows:

  • Call to the requiresNew function is terminated with an exception.
  • Explicit rollback is indicated in the requiresNew function.

If the above rollback conditions are not met, the commit is performed.

Transactional flows

Only R2dbcDatabase provides the flowTransaction function that constructs a transactional flow:

val db = R2dbcDatabase("r2dbc:h2:mem:///example;DB_CLOSE_DELAY=-1")

val transactionalFlow: Flow<Address> = db.flowTransaction {
    val a = Meta.address
    val address = db.runQuery {
        QueryDsl.from(a).where { a.addressId eq 15 }.first()
    }
    db.runQuery { 
        QueryDsl.update(a).single(address.copy(street = "TOKYO")) 
    }
    val addressFlow = db.flowQuery { 
        QueryDsl.from(a).orderBy(a.addressId)
    }
    emitAll(addressFlow)
}

// Transaction is executed
val list = transactionalFlow.toList()

In the above example, the call to the flowTransaction function only constructs a flow. The transaction is executed for the first time when the transactionalFlow is collected.

Last modified March 11, 2022: Update the title and linkTitle (cf9ed4f)