CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-springframework-boot--spring-boot-starter-jooq

Starter for using jOOQ to access SQL databases with JDBC, providing auto-configuration and Spring integration

Pending
Overview
Eval results
Files

transaction-integration.mddocs/

Transaction Integration

Integration between jOOQ and Spring's transaction management system, allowing jOOQ operations to participate seamlessly in Spring-managed transactions.

Capabilities

SpringTransactionProvider

Allows Spring transactions to be used with jOOQ by implementing jOOQ's TransactionProvider interface.

/**
 * TransactionProvider implementation that integrates jOOQ with Spring's transaction management
 * Automatically configured when PlatformTransactionManager is available
 */
public class SpringTransactionProvider implements TransactionProvider {
    
    /**
     * Create a new SpringTransactionProvider with the given transaction manager
     * @param transactionManager Spring's platform transaction manager
     */
    public SpringTransactionProvider(PlatformTransactionManager transactionManager);
    
    /**
     * Begin a new transaction context
     * Creates a nested transaction with PROPAGATION_NESTED
     * @param context the jOOQ transaction context
     */
    @Override
    public void begin(TransactionContext context);
    
    /**
     * Commit the current transaction
     * @param ctx the jOOQ transaction context
     */
    @Override
    public void commit(TransactionContext ctx);
    
    /**
     * Rollback the current transaction
     * @param ctx the jOOQ transaction context  
     */
    @Override
    public void rollback(TransactionContext ctx);
}

SpringTransaction

Adapter that wraps Spring's TransactionStatus for use with jOOQ's Transaction interface.

/**
 * Adapts a Spring TransactionStatus for jOOQ Transaction interface
 * Used internally by SpringTransactionProvider
 */
class SpringTransaction implements Transaction {
    
    /**
     * Create a new SpringTransaction wrapping the given TransactionStatus
     * @param transactionStatus Spring's transaction status
     */
    SpringTransaction(TransactionStatus transactionStatus);
    
    /**
     * Get the wrapped Spring TransactionStatus
     * @return the underlying TransactionStatus
     */
    TransactionStatus getTxStatus();
}

Usage Examples:

Basic Transactional Service

@Service
@Transactional
public class OrderService {
    
    @Autowired
    private DSLContext dsl;
    
    public void processOrder(Order order) {
        // Insert order - participates in Spring transaction
        dsl.insertInto(ORDER)
           .set(ORDER.ID, order.getId())
           .set(ORDER.CUSTOMER_ID, order.getCustomerId())
           .set(ORDER.TOTAL, order.getTotal())
           .execute();
        
        // Insert order items - same transaction
        for (OrderItem item : order.getItems()) {
            dsl.insertInto(ORDER_ITEM)
               .set(ORDER_ITEM.ORDER_ID, order.getId())
               .set(ORDER_ITEM.PRODUCT_ID, item.getProductId())
               .set(ORDER_ITEM.QUANTITY, item.getQuantity())
               .execute();
        }
        
        // Update inventory - still same transaction
        updateInventory(order.getItems());
    }
    
    private void updateInventory(List<OrderItem> items) {
        for (OrderItem item : items) {
            dsl.update(INVENTORY)
               .set(INVENTORY.QUANTITY, INVENTORY.QUANTITY.minus(item.getQuantity()))
               .where(INVENTORY.PRODUCT_ID.eq(item.getProductId()))
               .execute();
        }
    }
}

Manual Transaction Management

@Service
public class BatchProcessingService {
    
    @Autowired
    private DSLContext dsl;
    
    @Autowired 
    private PlatformTransactionManager transactionManager;
    
    public void processBatch(List<Data> dataList) {
        TransactionDefinition def = new DefaultTransactionDefinition();
        TransactionStatus status = transactionManager.getTransaction(def);
        
        try {
            for (Data data : dataList) {
                // jOOQ operations automatically participate in the transaction
                dsl.insertInto(BATCH_DATA)
                   .set(BATCH_DATA.VALUE, data.getValue())
                   .set(BATCH_DATA.PROCESSED_AT, LocalDateTime.now())
                   .execute();
            }
            
            transactionManager.commit(status);
        } catch (Exception e) {
            transactionManager.rollback(status);
            throw e;
        }
    }
}

Transaction Propagation

@Service
public class UserService {
    
    @Autowired
    private DSLContext dsl;
    
    @Autowired
    private AuditService auditService;
    
    @Transactional
    public void createUser(User user) {
        // Main transaction
        dsl.insertInto(USER)
           .set(USER.NAME, user.getName())
           .set(USER.EMAIL, user.getEmail())
           .execute();
        
        // Audit in same transaction by default
        auditService.logUserCreation(user.getId());
    }
    
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void createUserWithSeparateAudit(User user) {
        // Main transaction
        dsl.insertInto(USER)
           .set(USER.NAME, user.getName()) 
           .set(USER.EMAIL, user.getEmail())
           .execute();
        
        // Audit in separate transaction - will commit even if main fails
        auditService.logUserCreationSeparate(user.getId());
    }
}

@Service
public class AuditService {
    
    @Autowired
    private DSLContext dsl;
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void logUserCreation(Long userId) {
        // Participates in existing transaction
        dsl.insertInto(AUDIT_LOG)
           .set(AUDIT_LOG.USER_ID, userId)
           .set(AUDIT_LOG.ACTION, "CREATE")
           .execute();
    }
    
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void logUserCreationSeparate(Long userId) {
        // Always runs in new transaction
        dsl.insertInto(AUDIT_LOG)
           .set(AUDIT_LOG.USER_ID, userId)
           .set(AUDIT_LOG.ACTION, "CREATE")
           .execute();
    }
}

Exception Handling with Transactions

@Service
public class PaymentService {
    
    @Autowired
    private DSLContext dsl;
    
    @Transactional(rollbackFor = Exception.class)
    public void processPayment(Payment payment) throws PaymentException {
        try {
            // Validate payment
            validatePayment(payment);
            
            // Record payment attempt
            dsl.insertInto(PAYMENT_ATTEMPT)
               .set(PAYMENT_ATTEMPT.AMOUNT, payment.getAmount())
               .set(PAYMENT_ATTEMPT.STATUS, "PROCESSING")
               .execute();
            
            // Process with external service
            processWithGateway(payment);
            
            // Update status on success
            dsl.update(PAYMENT_ATTEMPT)
               .set(PAYMENT_ATTEMPT.STATUS, "SUCCESS")
               .where(PAYMENT_ATTEMPT.ID.eq(payment.getId()))
               .execute();
               
        } catch (PaymentException e) {
            // Transaction will be rolled back automatically
            // Both INSERT and UPDATE will be undone
            throw e;
        }
    }
    
    @Transactional(noRollbackFor = BusinessException.class)
    public void processPaymentWithBusinessExceptionHandling(Payment payment) {
        // Business exceptions won't trigger rollback
        // Only runtime exceptions and errors will
    }
}

Key Integration Points

Automatic Transaction Participation

  • jOOQ operations automatically participate in Spring-managed transactions
  • No additional configuration needed - works out of the box
  • Supports all Spring transaction propagation levels
  • Works with @Transactional annotations and programmatic transaction management

Connection Management

  • Uses TransactionAwareDataSourceProxy to ensure connection reuse within transactions
  • Properly releases connections when transactions complete
  • Handles connection pooling integration seamlessly

Nested Transaction Support

  • Supports Spring's nested transaction capability
  • Uses PROPAGATION_NESTED by default for jOOQ-initiated transactions
  • Integrates with savepoint management where supported by the database

Rollback Behavior

  • Automatic rollback on runtime exceptions
  • Configurable rollback rules via @Transactional attributes
  • Proper cleanup of jOOQ resources on rollback
  • Maintains consistency between Spring and jOOQ transaction states

Install with Tessl CLI

npx tessl i tessl/maven-org-springframework-boot--spring-boot-starter-jooq

docs

auto-configuration.md

configuration.md

exception-handling.md

index.md

testing-integration.md

transaction-integration.md

tile.json