Transaction Management

Loading concept...

🏦 Transaction Management in Spring

The Bank Vault Story


Imagine you’re running a magical bank where wizards come to transfer gold coins. Every transfer must follow one golden rule: either the entire transfer completes, or nothing happens at all. No partial magic allowed!

This is exactly what Transaction Management does in Spring. Let’s explore this magical world together!


🎯 What We’ll Learn

  1. DataSource Configuration – Setting up our bank vault
  2. Transaction Concepts – The rules of safe transfers
  3. Declarative Transactions – Magic spells that protect our transfers
  4. Transaction Propagation – When transfers call other transfers
  5. Transaction Internals – How the magic actually works

📦 1. DataSource Configuration

The Story

Before any wizard can transfer gold, we need to build our vault and connect it to our bank. The DataSource is like the key that opens the vault door.

What is a DataSource?

Think of it as:

  • 🔑 A master key to your database
  • 🏊 A pool of connections waiting to be used
  • 📞 A phone line that connects your app to the database

Simple Example

@Configuration
public class DataConfig {

    @Bean
    public DataSource dataSource() {
        HikariDataSource ds = new HikariDataSource();
        ds.setJdbcUrl("jdbc:mysql://localhost:3306/bank");
        ds.setUsername("banker");
        ds.setPassword("secret");
        ds.setMaximumPoolSize(10);
        return ds;
    }
}

Spring Boot Way (Even Simpler!)

# application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/bank
    username: banker
    password: secret
    hikari:
      maximum-pool-size: 10

🎨 Visual Flow

graph TD A[Your App] --> B[DataSource] B --> C[Connection Pool] C --> D[#40;Database#41;] C --> E[Connection 1] C --> F[Connection 2] C --> G[Connection N...]

Key Points

  • HikariCP is the default pool in Spring Boot (super fast!)
  • ✅ Pool size matters: too small = waiting, too big = waste
  • ✅ Always close connections (Spring does this for you!)

🎭 2. Transaction Concepts

The Story

Remember our wizard gold transfer? Let’s say Alice wants to send 100 gold coins to Bob. What needs to happen?

  1. Take 100 coins from Alice’s account
  2. Add 100 coins to Bob’s account

But what if step 2 fails? Alice loses coins, Bob gets nothing! 😱

The ACID Magic Shield

Transactions have four magical protections called ACID:

Letter Stands For Meaning
A Atomicity All or nothing!
C Consistency Rules always followed
I Isolation Transfers don’t peek at each other
D Durability Once done, it’s saved forever

Real Example: The Transfer

// WITHOUT transaction - DANGEROUS!
aliceAccount.withdraw(100);  // ✅ Done
// 💥 CRASH HERE!
bobAccount.deposit(100);     // ❌ Never happens!
// Result: Alice lost 100 coins forever!

// WITH transaction - SAFE!
@Transactional
public void transfer(int amount) {
    aliceAccount.withdraw(amount);  // Step 1
    bobAccount.deposit(amount);      // Step 2
    // If ANYTHING fails, both steps are undone!
}

🎨 Visual: What Happens on Failure

graph TD A[Start Transfer] --> B[Take from Alice] B --> C{Success?} C -->|Yes| D[Give to Bob] C -->|No| E[Rollback!] D --> F{Success?} F -->|Yes| G[Commit ✅] F -->|No| E E --> H[Alice gets coins back]

Key Points

  • Atomicity = Your safety net
  • Rollback = Undo button when things go wrong
  • Commit = Save permanently when all is good

✨ 3. Declarative Transactions

The Story

Instead of writing complex code to manage transactions, Spring lets you use a magic spell (annotation). Just say @Transactional and Spring handles everything!

The Magic Annotation

@Service
public class BankService {

    @Transactional
    public void transferGold(Long fromId, Long toId, int amount) {
        Account from = accountRepo.findById(fromId);
        Account to = accountRepo.findById(toId);

        from.withdraw(amount);
        to.deposit(amount);

        // Spring automatically:
        // ✅ Starts transaction before method
        // ✅ Commits if no exception
        // ✅ Rollbacks if exception thrown
    }
}

Configuration Options

@Transactional(
    readOnly = false,           // Can we write?
    timeout = 30,               // Max seconds
    isolation = Isolation.READ_COMMITTED,
    rollbackFor = Exception.class
)
public void transferGold(...) { }

Common Settings Explained

Setting What It Does Example
readOnly Optimizes for SELECT only readOnly = true
timeout Max execution time timeout = 30
rollbackFor Which errors trigger rollback rollbackFor = Exception.class

🎨 Visual: How It Works

graph TD A[Method Called] --> B[Spring Creates Proxy] B --> C[Start Transaction] C --> D[Run Your Code] D --> E{Exception?} E -->|No| F[Commit ✅] E -->|Yes| G[Rollback ↩️]

⚠️ Important Rule!

@Transactional only works when:

  • ✅ Called from outside the class
  • ❌ Won’t work for internal calls (same class)
@Service
public class BankService {

    @Transactional
    public void methodA() { }

    public void methodB() {
        methodA();  // ❌ Transaction NOT applied!
    }
}

🔄 4. Transaction Propagation

The Story

What happens when one transactional method calls another? This is where propagation comes in. It’s like asking: “Should we use the same train or get a new one?”

The Seven Propagation Types

Type What It Does Analogy
REQUIRED Join existing, or create new “I’ll take your train or get my own”
REQUIRES_NEW Always create new “I need my own train!”
SUPPORTS Join if exists, else none “I’ll ride if you have a train”
NOT_SUPPORTED Never use transaction “I’ll walk, thanks”
MANDATORY Must have existing “No train? I’m not going!”
NEVER Error if exists “Trains are forbidden!”
NESTED Create savepoint “Checkpoint in the journey”

Most Common: REQUIRED vs REQUIRES_NEW

@Service
public class OrderService {

    @Autowired
    private PaymentService paymentService;

    @Transactional  // REQUIRED by default
    public void placeOrder(Order order) {
        saveOrder(order);
        paymentService.processPayment(order);
        // Both use SAME transaction!
    }
}

@Service
public class PaymentService {

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void processPayment(Order order) {
        // This runs in its OWN transaction!
        // If this fails, order might still save
    }
}

🎨 Visual: REQUIRED vs REQUIRES_NEW

graph TD subgraph "REQUIRED #40;Same Train#41;" A1[Order Method] --> B1[Payment Method] B1 --> C1[Same Transaction] end subgraph "REQUIRES_NEW #40;New Train#41;" A2[Order Method] --> B2[Payment Method] A2 --> C2[Transaction 1] B2 --> D2[Transaction 2] end

When to Use What?

Scenario Use This
Related operations REQUIRED
Independent logging REQUIRES_NEW
Read-only queries SUPPORTS
Must have context MANDATORY

🔧 5. Transaction Internals

The Story

Ever wondered what happens under the hood when you write @Transactional? Let’s peek behind the curtain!

The Proxy Magic

Spring doesn’t change your code. Instead, it creates a wrapper (proxy) around your class:

You Call → [Proxy] → [Your Method] → [Proxy] → Result
             ↓                           ↓
        Start TX                    Commit/Rollback

How Spring Does It

// Your code:
@Transactional
public void transfer() { ... }

// What Spring actually creates:
public class BankService$Proxy {

    private BankService target;
    private TransactionManager txManager;

    public void transfer() {
        TransactionStatus status = txManager.getTransaction();
        try {
            target.transfer();  // Your actual code
            txManager.commit(status);
        } catch (Exception e) {
            txManager.rollback(status);
            throw e;
        }
    }
}

Key Components

Component Role
PlatformTransactionManager The boss that controls everything
TransactionDefinition Rules (timeout, isolation, etc.)
TransactionStatus Current state (active, completed)

🎨 Visual: Full Picture

graph TD A[Your Code] --> B[AOP Proxy] B --> C[TransactionInterceptor] C --> D[TransactionManager] D --> E[DataSource] E --> F[#40;Database#41;] D --> G[Begin TX] D --> H[Commit/Rollback]

The Transaction Manager

@Bean
public PlatformTransactionManager txManager(DataSource ds) {
    return new DataSourceTransactionManager(ds);
}

For JPA/Hibernate, use:

@Bean
public PlatformTransactionManager txManager(EntityManagerFactory emf) {
    return new JpaTransactionManager(emf);
}

Spring Boot Auto-Magic ✨

In Spring Boot, you don’t even need to configure this! It auto-creates the right transaction manager based on your dependencies.


🎯 Quick Summary

Concept One-Liner
DataSource Your database connection pool
ACID Atomic, Consistent, Isolated, Durable
@Transactional Magic spell for safe operations
Propagation Rules when transactions meet
Proxy Spring’s wrapper that does the magic

🚀 You Did It!

You now understand how Spring protects your data like a magical bank vault:

  1. ✅ Configure your vault (DataSource)
  2. ✅ Know the safety rules (ACID)
  3. ✅ Use magic spells (@Transactional)
  4. ✅ Handle nested operations (Propagation)
  5. ✅ Understand the magic (Proxies)

Next time you write @Transactional, you’ll know exactly what’s happening! 🎉

Loading story...

No Story Available

This concept doesn't have a story yet.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

Interactive Preview

Interactive - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Interactive Content

This concept doesn't have interactive content yet.

Cheatsheet Preview

Cheatsheet - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Cheatsheet Available

This concept doesn't have a cheatsheet yet.

Quiz Preview

Quiz - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Quiz Available

This concept doesn't have a quiz yet.