A database transaction defines the boundary within which application changes are committed or rolled back. In a Quarkus application using Hibernate, operations that modify the database must run inside a transaction: Hibernate needs it to propagate changes from entities to the database. Quarkus recommends placing transaction boundaries at application entry points, such as REST resource methods. section 7.5.1 section 7.5.3
Quarkus includes a transaction manager when an extension needs one. For transaction use outside that scope, add the quarkus-narayana-jta extension. Choose between declarative boundaries on CDI methods and manual handling with QuarkusTransaction. Distributed transactions in microservices require more care than these data-access patterns cover. section 7.5
For declarative handling, put JTA’s @Transactional on a CDI method that persists, updates, or deletes entities. It normally starts before the method and commits or rolls back when the method finishes, depending on specified exceptions. Its TxType controls participation:
- REQUIRED, the default, joins an incoming transaction or starts one. section 7.5.1
- REQUIRES_NEW starts a separate transaction and suspends an existing one; MANDATORY requires an existing transaction. section 7.5.1
- SUPPORTS joins if possible but can run without a transaction; NOT_SUPPORTED suspends one; NEVER rejects an incoming transaction. section 7.5.1
Persisting an inventory item
A GraphQL register mutation calls carRepository.persist(car) inside an @Transactional method. Its remove mutation finds a car by license-plate number and deletes it under the same annotation. A gRPC stream instead performs persistence inside a callback outside the CDI bean method; QuarkusTransaction.requiringNew().run(...) wraps each persist call so each car has its own transaction. The database operations are marked @Blocking in the gRPC service. section 7.2.2
Use QuarkusTransaction when an annotation does not put the operation inside the needed boundary. Its static API supports explicit begin, commit, and rollback, or wrappers around Runnable and Callable. Wrapper options include joining or requiring a transaction, a timeout, and an exception handler that chooses whether to commit or roll back. Avoid starting or suspending transactions for work that does not need them; doing so adds invocation overhead. section 7.5.2 section 7.5.1
A transaction also governs when pending entity changes reach the database. Hibernate normally flushes gathered SQL before commit or before a query. To check database constraints sooner, call an entity or repository flush method, or persistAndFlush; these methods can throw PersistenceException. Use early flushes sparingly because database communication consumes resources. section 7.5.3
Listing 7.25 Transaction wrappers provided by QuarkusTransaction
QuarkusTransaction.requiringNew().run(() -> { #1
// perform operation
});
var txResult = QuarkusTransaction.joiningExisting()
.timeout(30)
.exceptionHandler(throwable -> {
if (throwable instanceof AnyRecoverableException) {
return TransactionExceptionResult.COMMIT;
}
return TransactionExceptionResult.ROLLBACK;
}).call(() -> { #2
var result = // perform operation
return result;
});
Compare a new transaction around a Runnable with a Callable that joins an existing transaction and configures timeout and exception handling. section 7.5.2













