Tips to Understand the Difference Between Propagation.REQUIRED and REQUIRES_NEW

Anh Trần Tuấn - Aug 26 - - Dev Community

1. What is Transaction Propagation in Spring?

Before diving into the differences, it's important to understand what transaction propagation is. In Spring, transaction propagation determines how a method should handle existing transactions. It dictates whether a method should run within an existing transaction, create a new transaction, or not run within a transaction at all.

1.1 Propagation.REQUIRED

Propagation.REQUIRED is the default propagation type in Spring. When a method is annotated with @Transactional(propagation = Propagation.REQUIRED), it means that the method should run within an existing transaction if one exists. If there is no existing transaction, a new one will be created.

Example:

@Service
public class MyService {

    @Transactional(propagation = Propagation.REQUIRED)
    public void requiredMethod() {
        // Some database operations
    }
}
Enter fullscreen mode Exit fullscreen mode

In the example above, requiredMethod() will either join an existing transaction or start a new one if none exists.

1.2 Propagation.REQUIRES_NEW

Propagation.REQUIRES_NEW creates a new transaction, suspending any existing transaction. This means that even if there is an ongoing transaction, it will be paused, and a new transaction will be created for the method annotated with @Transactional(propagation = Propagation.REQUIRES_NEW).

Example:

@Service
public class MyService {

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void requiresNewMethod() {
        // Some database operations
    }
}
Enter fullscreen mode Exit fullscreen mode

In this case, requiresNewMethod() will always start a new transaction, regardless of whether a transaction already exists.

2. Differences Between Propagation.REQUIRED and Propagation.REQUIRES_NEW

Understanding the key differences between Propagation.REQUIRED and Propagation.REQUIRES_NEW is essential for making informed decisions in your transactional management.

2.1 Transaction Behavior

  • Propagation.REQUIRED : If there is an existing transaction, it will be joined. If not, a new transaction is started.
  • Propagation.REQUIRES_NEW : Always creates a new transaction, suspending any existing transaction.

2.2 Use Cases

Propagation.REQUIRED : Ideal for most cases where you want your method to participate in an existing transaction. For instance, if you're saving multiple related entities and want them to either all succeed or all fail together, Propagation.REQUIRED ensures this behavior.

Example Use Case:

@Transactional
public void saveEntities() {
    saveEntityA(); // Propagation.REQUIRED
    saveEntityB(); // Propagation.REQUIRED
}
Enter fullscreen mode Exit fullscreen mode

Both saveEntityA() and saveEntityB() will participate in the same transaction.

Propagation.REQUIRES_NEW : Useful when you need to ensure that a particular method runs in its own transaction, independent of any ongoing transaction. This is often used in scenarios like auditing or logging, where you want to ensure the operation is committed even if the main transaction fails.

Example Use Case:

@Transactional
public void processData() {
    processMainData(); // Propagation.REQUIRED
    logOperation(); // Propagation.REQUIRES_NEW
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logOperation() {
    // Logging operation
}
Enter fullscreen mode Exit fullscreen mode

Here, logOperation() will run in its own transaction, independent of processMainData().

2.3 Rollback Behavior

Propagation.REQUIRED : If an exception occurs, and the transaction is marked for rollback, the entire transaction, including any participating methods, will roll back.

Propagation.REQUIRES_NEW : If an exception occurs, the new transaction will roll back, but the original transaction can still proceed.

Example Scenario:

@Transactional
public void processWithException() {
    try {
        saveEntityA(); // Propagation.REQUIRED
        saveEntityB(); // Propagation.REQUIRES_NEW
    } catch (Exception e) {
        // Handle exception
    }
}
Enter fullscreen mode Exit fullscreen mode

If saveEntityB() throws an exception, only its transaction will be rolled back, and s*aveEntityA()* can still commit if it completes successfully.

3. Conclusion

Understanding the difference between Propagation.REQUIRED and Propagation.REQUIRES_NEW is crucial for effective transactional management in Spring. While Propagation.REQUIRED is suitable for most situations where you want methods to participate in a shared transaction, Propagation.REQUIRES_NEW is perfect for scenarios where a method must run independently of the ongoing transaction.

If you have any questions or need further clarification, feel free to leave a comment below!

Read posts more at : Tips to Understand the Difference Between Propagation.REQUIRED and REQUIRES_NEW

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .