Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Transaction Propagation Behaviors and Programmatic Transactions in Spring @Transactional

Tech 2

Tarnsaction Propagation Behaviors in @Transactional

Propagation Behaviors

@Transactional(propagation = Propagation.REQUIRED) // Join existing transaction or create new one (default)
@Transactional(propagation = Propagation.NOT_SUPPORTED) // Execute without transaction
@Transactional(propagation = Propagation.REQUIRES_NEW) // Always create new transaction, suspending existing one
@Transactional(propagation = Propagation.MANDATORY) // Must execute within existing transaction, throws exception otherwise
@Transactional(propagation = Propagation.NEVER) // Must execute without transaction, throws exception otherwise
@Transactional(propagation = Propagation.SUPPORTS) // Use transaction if caller has one, otherwise execute without
@Transactional(propagation = Propagation.NESTED) // Execute nested transaction if exists, otherwise create new

Isolation Levels

@Transactional(isolation = Isolation.READ_UNCOMMITTED) // Read uncommitted data (dirty reads, non-repeatable reads)
@Transactional(isolation = Isolation.READ_COMMITTED) // Read committed data (non-repeatable reads, phantom reads)
@Transactional(isolation = Isolation.REPEATABLE_READ) // Repeatable reads (phantom reads)
@Transactional(isolation = Isolation.SERIALIZABLE) // Serializable isolation

Database Defaults:

  • MySQL: REPEATABLE_READ
  • SQL Server: READ_COMMITTED
  • Oracle: Supports READ_COMMITTED and SERIALIZABLE (no dirty reads)

Transaction Isolation Concepts

  • Dirty Read: Reading uncommitted data from another transaction
  • Non-repeatable Read: Reading different results for same data within same transaction due to committed updates from other transactions
  • Repeatable Read: Consistent reads within same transaction, unaffected by other transactions' committed updates
  • Phantom Read: Reading newly inserted data committed by another transaction

@Transactional Annotation Attributes

// Read-only transaction
@Transactional(readOnly = true) // Default: false

// Transaction timeout
@Transactional(timeout = 30) // Default: -1 (no timeout)

// Rollback rules
@Transactional(rollbackFor = RuntimeException.class) // Single exception
@Transactional(rollbackFor = {RuntimeException.class, Exception.class}) // Multiple exceptions

// No-rollback rules
@Transactional(noRollbackFor = RuntimeException.class) // Single exception
@Transactional(noRollbackFor = {RuntimeException.class, Exception.class}) // Multiple exceptions

Common @Transactional Pitfalls

  • Method must be public
  • Only unchecked exceptions trigger rollback by default
  • Database engine must support transactions (e.g., MySQL InnoDB)
  • Spring must scan the package containing the class
  • Avoid calling this.method() within same class (bypasses proxy)

Programmatic Transaction Management

Approach 1: Using PlatformTransactionManager

@Autowired
private PlatformTransactionManager txManager;

public void executeWithTransaction() {
    TransactionStatus status = txManager.getTransaction(new DefaultTransactionDefinition());
    
    try {
        for (int counter = 0; counter < 10; counter++) {
            dataService.saveRecord(counter);
            if (counter == 5) {
                throw new RuntimeException("Transaction test exception");
            }
        }
        txManager.commit(status);
    } catch (Exception error) {
        txManager.rollback(status);
        throw error;
    }
}

Approach 2: Using TransactionTemplate

@Resource
private TransactionTemplate transactionTemplate;

public void executeWithTemplate() {
    transactionTemplate.execute(status -> {
        try {
            dataService.saveRecord(1);
            dataService.saveRecord(2);
        } catch (Exception error) {
            status.setRollbackOnly();
            return false;
        }
        return true;
    });
}

Note: Programmatic transactions can be combined with @Transactional annotations and both will work correctly.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.