CodeGym /Courses /Module 5. Spring /What are transactions and why you need them

What are transactions and why you need them

Module 5. Spring
Level 6 , Lesson 0
Available

Every day we deal with operations that must be done completely or not at all. Think about a bank transfer: money must disappear from one account and appear in another. It can't get stuck halfway. In programming, such operations are called transactions.

Transaction as a basic unit of work

A transaction is a group of operations that must run as a single unit. Either all operations succeed (commit), or the system rolls everything back (rollback), as if nothing happened. It's like game save checkpoints: if something goes wrong, you can always go back to the last save.

For a transaction to be considered correct, it must have the following properties, grouped under the acronym ACID:

Property Description
Atomicity (Atomicity) All operations inside the transaction run as a single unit. All or nothing
Consistency (Consistency) After the transaction finishes, the system ends up in a valid state
Isolation (Isolation) Transaction operations are isolated from concurrent transactions (no "interference")
Durability (Durability) After a transaction completes, its results are preserved even if the system crashes

Imagine a bank transfer. You want to send money from your account to a friend's account. The process can be split into these steps: 1. Decrease the amount on your account. 2. Increase the amount on your friend's account.

If a failure happens between these steps (for example, the connection to the bank drops), we risk either "losing" money or "creating" it out of thin air. To prevent that, both operations are wrapped in a transaction. If one of the steps fails, all changes are rolled back and the system returns to its original state.


Why transactions matter in apps

In dev work, transactions play a key role in keeping data correct, especially when apps talk to databases. Let's break down why you can't really live without them.

Ensuring data consistency

Back to the bank transfer example: imagine the bank server suddenly crashes after debiting your account. Without transactions your friend won't get the money, and you'll be out cash. Not a great look, right?

Transactions handle this cleanly: either the money is transferred, or it gets returned to your account — no stuck payments. This is critical for serious apps: e-commerce sites, booking systems, medical platforms.

Working in multi-user environments

Modern apps often face situations where multiple users try to change the same data:

  • Two buyers both target the last pair of sneakers
  • Multiple managers edit the same customer card in the CRM at the same time

Without transactions this can lead to real data chaos. Transactions act like a smart traffic controller — they keep operations from stepping on each other.


Problems transactions solve

Now let's look at the main problems transactions help solve.

Preventing partial changes

Imagine you're working on an order model in an online store. Creating an order might include these steps:

  1. Create a new order record in the database.
  2. Decrease the available product quantity in inventory.
  3. Send a notification to the user.

If a failure happens, say, on the second step, you'll end up with a "partially completed" state: the order exists in the system, but the product is still marked as available. That can cause big issues, especially in scalable systems. Transactions help avoid those scenarios.

Data integrity during failures

Failures are inevitable. For example:

  • Something went wrong while saving data to the database.
  • The network went down.
  • The application threw an exception.

With a solid transactional system you can be sure that no "corrupted" changes end up in your database.

Eliminating conflicts during concurrent work

Another issue is when multiple processes or users try to modify the same data at the same time. For example:

  1. Employee A added a comment in the CRM.
  2. Employee B simultaneously deleted that same comment.

Who wins? Without isolation, the outcome can be unpredictable. But with proper transaction configuration, concurrent transactions are protected from interfering with each other.


Example: transactions in an online store

Let's build a simple example where transactions are used to process an order in an online store. Our scenario:

  1. Create a new order record.
  2. Decrease the product stock in inventory.
  3. If a failure happens at any step, roll back all changes.

@Service
public class OrderService {
    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private InventoryService inventoryService;

    @Transactional
    public void processOrder(OrderRequest orderRequest) {
        // Step 1: Creating a new order
        Order order = new Order();
        order.setProductId(orderRequest.getProductId());
        order.setQuantity(orderRequest.getQuantity());
        order.setStatus("PROCESSING");
        orderRepository.save(order);

        // Step 2: Reducing stock in inventory
        inventoryService.reduceStock(orderRequest.getProductId(), orderRequest.getQuantity());

        // Step 3: Update order status to "COMPLETED"
        order.setStatus("COMPLETED");
        orderRepository.save(order);
    }
}

What's happening here?

  • We mark the processOrder() method as transactional using the @Transactional annotation. That means all operations inside the method run in a single transaction.
  • If an error happens at any point (for example, the product is out of stock), the changes will be automatically rolled back and the database will stay consistent.

Error example and rollback

Let's add an "artificial" error to check that the transaction actually rolls back.


public void reduceStock(String productId, int quantity) {
    int currentStock = inventoryRepository.getStock(productId);
    if (currentStock < quantity) {
        throw new RuntimeException("Insufficient stock for product: " + productId);
    }
    inventoryRepository.updateStock(productId, currentStock - quantity);
}

If there's not enough product, the reduceStock method will throw an exception and the whole transaction will be canceled: the order won't be saved, and the inventory won't be changed.


Real-world usage

In real projects, transactions are used almost everywhere:

  • Banking operations (transfers, deposits, withdrawals).
  • Orders and bookings (buying tickets, hotel reservations).
  • Managing data in enterprise systems (CRM, ERP).

Why this matters for you — if you're asked in an interview how to handle a bank operation or protect data from conflicts, as an experienced Java developer with Spring you won't just talk about transactions, you'll show code with @Transactional.

Now we're ready to move on to the next step: managing transactions in Spring using the @Transactional annotation and other tools.

Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION