Learn / Frameworks / Spring Boot / Transactions and Locking

Spring Boot · Lesson 8 of 15

Transactions and Locking

@Transactional boundaries, isolation and optimistic locking.

  • Intermediate
  • 16 min read
  • 3 objectives

Before this lessonLesson 7: Validation and Problem Details

What you will learn

  • Mark a service transactional
  • Use @Version
  • Avoid self-invocation

Your Progress

0 of 15 lessons 0%

  • Lessons0 / 15
  • Completed0
  • Est. time left~ 4 hours

Create a free account to keep your progress on every device.

@Transactional wraps a method in a database transaction. It only works when called through the Spring proxy, on a public method, from another bean.

Where it belongs

@Service
public class TransferService {
    private final AccountRepository accounts;

    @Transactional
    public void transfer(long fromId, long toId, long cents) {
        Account from = accounts.findByIdForUpdate(fromId).orElseThrow();
        Account to = accounts.findByIdForUpdate(toId).orElseThrow();
        from.debit(cents);
        to.credit(cents);
    }
}

Keep transactions on the service layer, not on controllers, and as short as possible. Do not call HTTP inside one.

Optimistic locking

@Entity
public class Product {
    @Id @GeneratedValue Long id;
    long stock;
    @Version long version;
}

A stale update throws OptimisticLockException. Catch it and retry, or tell the user to refresh.

Up next · Lesson 9Caching with Spring Cache@Cacheable, @CacheEvict and a Redis cache manager.