Posted in

How to use @Transactional for database transactions in Spring?

In the world of enterprise application development, managing database transactions effectively is crucial for maintaining data integrity and consistency. Spring, a widely – adopted Java framework, provides the @Transactional annotation as a powerful tool to simplify transaction management. As a Spring supplier, I am here to share in – depth knowledge on how to use @Transactional for database transactions in Spring. Spring

Understanding Database Transactions

Before delving into the @Transactional annotation, it’s essential to understand what database transactions are. A database transaction is a sequence of one or more SQL statements that are treated as a single unit of work. The four key properties of a transaction, known as ACID properties, are:

  1. Atomicity: A transaction is atomic, meaning it is an all – or – nothing operation. Either all the statements in a transaction are successfully executed, or none of them are.
  2. Consistency: A transaction must bring the database from one consistent state to another. If a transaction fails, the database should remain in a consistent state.
  3. Isolation: Transactions should execute independently of each other. One transaction should not interfere with the data being modified by another transaction.
  4. Durability: Once a transaction is committed, its changes to the database are permanent and will survive system failures.

The Role of @Transactional in Spring

Spring’s @Transactional annotation simplifies the process of managing database transactions. It allows developers to declaratively define transaction boundaries without writing a lot of boilerplate code. When a method is annotated with @Transactional, Spring takes care of starting a transaction before the method is invoked, committing the transaction if the method executes successfully, and rolling back the transaction if an exception occurs.

Enabling @Transactional

To use the @Transactional annotation, you first need to enable Spring’s transaction management. This can be done in different ways depending on your Spring configuration.

Java Configuration:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

@Configuration
@EnableTransactionManagement
public class AppConfig {

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

In the above code, @EnableTransactionManagement is used to enable Spring’s transaction management, and a PlatformTransactionManager bean is created. The PlatformTransactionManager is responsible for managing transactions.

XML Configuration:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema - instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring - beans.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring - tx.xsd">

    <tx:annotation - driven transaction - manager="transactionManager"/>

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>

Here, <tx:annotation - driven> is used to enable transaction management, and a DataSourceTransactionManager bean is defined.

Using @Transactional on Methods

Once transaction management is enabled, you can use the @Transactional annotation on methods.

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {

    @Transactional
    public void createUser(User user) {
        // Code to insert the user into the database
    }
}

In the UserService class, the createUser method is annotated with @Transactional. This means that when this method is called, Spring will start a transaction before the method execution. If the createUser method completes successfully, Spring will commit the transaction. If an exception occurs during the execution of the createUser method, Spring will roll back the transaction.

Configuring @Transactional

The @Transactional annotation provides several attributes to customize transaction behavior.

propagation

The propagation attribute defines how a transactional method interacts with an existing transaction. Some common propagation values are:

  • Propagation.REQUIRED: If a transaction already exists, the method will execute within that transaction. Otherwise, a new transaction will be created. This is the default value.
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
    // Method implementation
}
  • Propagation.REQUIRES_NEW: A new transaction will be created, and the current transaction (if any) will be suspended until the new transaction completes.
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
    // Method implementation
}

isolation

The isolation attribute defines the isolation level of a transaction. Isolation levels determine how one transaction affects other concurrent transactions. Common isolation levels are:

  • Isolation.READ_UNCOMMITTED: Allows dirty reads, where one transaction can read uncommitted changes made by another transaction.
  • Isolation.READ_COMMITTED: Prevents dirty reads. A transaction can only read committed data.
@Transactional(isolation = Isolation.READ_COMMITTED)
public void methodC() {
    // Method implementation
}
  • Isolation.REPEATABLE_READ: Ensures that a transaction will see the same data throughout its execution, even if other transactions modify the data.
  • Isolation.SERIALIZABLE: The highest level of isolation, which ensures that transactions are executed serially, preventing all types of concurrency issues.

timeout

The timeout attribute specifies the maximum time (in seconds) that a transaction can take. If the transaction exceeds this time limit, it will be rolled back.

@Transactional(timeout = 30)
public void methodD() {
    // Method implementation
}

readOnly

The readOnly attribute indicates that the transaction is read – only. Setting this attribute to true can be used as a hint to the underlying database to optimize the transaction for read operations.

@Transactional(readOnly = true)
public User getUserById(Long id) {
    // Method to retrieve a user by ID
    return null;
}

rollbackFor and noRollbackFor

The rollbackFor attribute allows you to specify the exceptions for which the transaction should be rolled back. The noRollbackFor attribute allows you to specify the exceptions for which the transaction should not be rolled back.

@Transactional(rollbackFor = {CustomException.class}, noRollbackFor = {MinorException.class})
public void methodE() throws CustomException, MinorException {
    // Method implementation
}

Using @Transactional on Classes

In addition to using @Transactional on methods, you can also use it on classes. When used on a class, the annotation applies to all public methods in the class.

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class OrderService {

    public void createOrder(Order order) {
        // Code to create an order
    }

    public void cancelOrder(Order order) {
        // Code to cancel an order
    }
}

In this OrderService class, both the createOrder and cancelOrder methods will be transactional because the class is annotated with @Transactional.

Best Practices

  1. Transaction Scope: Keep the transaction scope as small as possible. Long – running transactions can increase the likelihood of concurrency issues and resource contention.
  2. Explicit Configuration: Whenever possible, explicitly configure the propagation, isolation, and other attributes of the @Transactional annotation to avoid unexpected behavior.
  3. Exception Handling: Be careful with exception handling within transactional methods. Unhandled exceptions will usually cause the transaction to roll back, so make sure to handle exceptions appropriately.

Conclusion

The @Transactional annotation in Spring is a powerful tool for managing database transactions. It simplifies the development process by allowing developers to declaratively define transaction boundaries and customize transaction behavior. As a Spring supplier, we can provide you with comprehensive support in leveraging the full potential of Spring’s transaction management capabilities. Whether you are new to Spring or looking to optimize your existing Spring – based applications, our team of experts is ready to assist you.

Spare Parts If you are interested in enhancing your application’s transaction management or starting a new project with Spring, we encourage you to reach out for a procurement discussion. Our solutions are tailored to meet your specific business requirements, ensuring high – performance and reliable database transactions.

References

  • Spring Framework Documentation.
  • Java Enterprise Application Development Books.

Xinxiang Fengda Machinery Co., Ltd.
We’re well-known as one of the leading spring manufacturers and suppliers in China, specialized in providing high quality customized service for global clients. We warmly welcome you to buy high-grade spring made in China here from our factory.
Address: No.16 Wangguanying Village, Kangcun Town, Huojia County, Xinxiang City, Henan Province, China
E-mail: xxfdjx@163.com
WebSite: https://www.flipflowscreen.com/