What does @transactional do in Java?

Miya 40 Published: 12/02/2024

What does @transactional do in Java?

I'd be happy to explain what @Transactional does in Java!

In Java, the @Transactional annotation is used to define a transaction boundary around a method or code block. Transactions are a fundamental concept in database management that ensure consistency and integrity of data by either committing or rolling back changes made during a series of operations.

When you annotate a method with @Transactional, Spring's Transaction Management API wraps the entire execution of the method within a transaction, which can be one of two types:

Local transactions: The transaction is tied to the current thread and lasts only for the duration of the method call. Global transactions: The transaction is propagated across multiple threads, allowing multiple methods to participate in the same transaction.

Here are some key aspects of @Transactional:

Transaction scope: The annotation defines the scope of the transaction, which determines when the transaction starts and ends. Propagation: You can control how the transaction is propagated using attributes like propagation or transactional. For example, PROPAGATION_REQUIRED means that the method must be executed within an existing transaction. If no transaction exists, a new one will be created. Conversely, PROPAGATION_SUPPORTS allows the method to execute without a transaction if one doesn't exist. Rollback: In case of an exception or error during execution, Spring can automatically roll back the transaction using rollbackFor or rollbackForClass. Commit: When the method executes successfully, the transaction is committed using commitNoRollbackOnCompletion.

To illustrate this, let's consider a simple example:

@Service

public class UserService {

@Transactional(propagation = Propagation.REQUIRED)

public void updateUser(String username) {

// Simulate database operation: update user info

System.out.println("Updating user...");

// Intentionally throw an exception to demonstrate rollback

if (username.equals(" invalid")) {

throw new RuntimeException("Invalid username");

}

System.out.println("User updated successfully!");

}

}

In this example, the updateUser method is annotated with @Transactional. When called, it starts a new transaction. If an exception occurs during execution (e.g., due to invalid username), Spring will automatically roll back the transaction using the configured rollback mechanism.

By using @Transactional, you can ensure that your business logic executes within a consistent and reliable context, making it easier to manage complex operations involving multiple database calls or system resources.

I hope this helps! Let me know if you have any questions or need further clarification.

Java transaction management example

Java Transaction Management Example!

In the world of software development, transactions are essential for maintaining data consistency and integrity. Imagine you're working on an e-commerce platform, and you want to ensure that when a customer purchases an item, the inventory level is updated accordingly. This can be achieved through transaction management in Java.

Let's dive into a simple example:

Step 1: Create a Transaction Manager

You'll need a TransactionManager class to manage transactions. In this case, we'll use the UserTransaction API from JEE (Java EE) or DataSourceTransactionManager from Spring.

import javax.transaction.UserTransaction;

import org.springframework.jdbc.datasource.DataSourceTransactionManager;

public class TransactionManager {

// For UserTransaction API

public static UserTransaction createTx() {

return new InitialContext().lookup("java:comp/UserTransaction");

}

// For DataSourceTransactionManager

public static DataSourceTransactionManager createTx(DataSource dataSource) {

return new DataSourceTransactionManager(dataSource);

}

}

Step 2: Create a Transaction-Enabled DAO

Next, you'll need to create a DAO (Data Access Object) that's transaction-enabled. This will allow you to encapsulate your data access logic and manage transactions.

import javax.persistence.EntityManager;

import org.springframework.beans.factory.annotation.Autowired;

public class CustomerDAO {

private EntityManager em;

@Autowired

public CustomerDAO(EntityManager em) {

this.em = em;

}

public void updateCustomer(int customerId, String newEmail) {

// Your data access logic here

em.createQuery("UPDATE customers SET email = :newEmail WHERE id = :customerId")

.setParameter("newEmail", newEmail)

.setParameter("customerId", customerId)

.executeUpdate();

}

}

Step 3: Perform Transactions

Now, let's see how to perform transactions using the TransactionManager and CustomerDAO.

import java.sql.SQLException;

public class Main {

public static void main(String[] args) throws Exception {

// Create a TransactionManager (e.g., UserTransaction or DataSourceTransactionManager)

UserTransaction tx = TransactionManager.createTx();

try {

// Start the transaction

tx.begin();

// Update the customer's email address (encapsulated in CustomerDAO)

CustomerDAO dao = new CustomerDAO(em);

dao.updateCustomer(1, "[email protected]");

// Commit the transaction

tx.commit();

} catch (Exception e) {

try {

// Roll back the transaction if an exception occurs

tx.rollback();

} catch (Exception ex) {

System.out.println("Error rolling back: " + ex.getMessage());

}

}

}

}

In this example, we've demonstrated basic transaction management in Java using the UserTransaction API and Spring's DataSourceTransactionManager. This allows you to encapsulate your data access logic and ensure that transactions are properly started, committed, or rolled back as needed.

Remember to handle exceptions and potential issues during transaction execution by incorporating error handling mechanisms. This ensures that your system remains robust and resilient in the face of unexpected errors!