Spring Boot_Transaction Management
Spring Boot_Transaction Management
Annotation
@Transactional Annotation
In this step, we will create a spring boot project. For this, we will be
using Spring Initializr. To create a spring boot project please refer to How
to Create a Spring Boot Project?
We will add the required dependencies for our spring boot application.
server.port = 9090
#database configuration
spring.datasource.url=jdbc:mysql://localhost:3306/employee_db
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dial
ect
#the ddl-auto=update : It will create the entity schema and map it to db
automatically
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
Note: Please add your database username & password along with the
database path.
In this step, we will create our model class. Here, we will be creating two
model classes, Employee and Address. While creating the model class
we will be using Lombok Library.
Employee.java
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Entity
@Table(name="EMP_INFO")
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Address.java
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Entity
@Table(name="ADD_INFO")
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@OneToOne
EmployeeRepository.java
import org.springframework.data.jpa.repository.JpaRepository;
import
com.geeksforgeeks.transactionmanagement.model.Employee;
AddressRepository.java
import org.springframework.data.jpa.repository.JpaRepository;
import
com.geeksforgeeks.transactionmanagement.model.Address;
public interface AddressRepository extends JpaRepository<Address,
Integer> {
You can use @Transactional annotation in service layer which will result
interacting with the database. In this step, we will create a service layer
for our application and add business logic to it. For this, we will be
creating two classes EmployeeService and AddressService. In
EmployeeService class we are throwing an exception.
EmployeeService.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import
org.springframework.transaction.annotation.Transactional;
import
com.geeksforgeeks.transactionmanagement.model.Address;
import
com.geeksforgeeks.transactionmanagement.model.Employee;
import
com.geeksforgeeks.transactionmanagement.repository.Employee
Repository;
@Service
@Autowired
@Autowired
private AddressService addressService;
@Transactional
Employee employeeSavedToDB =
this.employeeRepository.save(employee);
address.setId(123L);
address.setAddress("Varanasi");
address.setEmployee(employee);
// of AddressService class
this.addressService.addAddress(address);
return employeeSavedToDB;
AddressService.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import
com.geeksforgeeks.transactionmanagement.model.Address;
import
com.geeksforgeeks.transactionmanagement.repository.AddressR
epository;
@Service
return addressSavedToDB;
In this step, we will create a controller for our application. For this, we will
create a Controller class and add all the mappings to it.
Controller.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import
org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import
com.geeksforgeeks.transactionmanagement.model.Employee;
import
com.geeksforgeeks.transactionmanagement.service.EmployeeSer
vice;
@RestController
@RequestMapping("/api/employee")
public class Controller {
@Autowired
@PostMapping("/add")
Employee employeeSavedToDB =
this.employeeService.addEmployee(employee);
In this step, we will run our application. Once, we run our application using
hibernate mapping in our database required tables will be created.
As we can see in logs, our table has been created. We can also confirm it
by looking at our database.
Now, we will request our application for adding an employee to it, using
postman. To learn more about postman please refer to Postman – Working,
HTTP Request & Responses. Once, we hit the request, the request
moves from the controller to the service layer where our business
logic is present.
As we can see in the above response we have added an employee. We
can also check our database for employee data and address data.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import
org.springframework.transaction.annotation.Transactional;
import
com.geeksforgeeks.transactionmanagement.model.Address;
import
com.geeksforgeeks.transactionmanagement.model.Employee;
import
com.geeksforgeeks.transactionmanagement.repository.Employee
Repository;
@Service
@Autowired
@Autowired
Employee employeeSavedToDB =
this.employeeRepository.save(employee);
address.setId(123L);
address.setAddress("Varanasi");
address.setEmployee(employee);
// of AddressService class
this.addressService.addAddress(address);
return employeeSavedToDB;
}
}
Now, we will delete our table from the database and again run our
application and will request the application to create an employee.
As we can see in the above media file, we have initialized the address
object as null and requested the application, we have an employee
created in the database but the address information is not, as we have
received a null pointer exception. But, this is not good practice in
transaction management, as employees should be saved only when the
address is saved and vice-versa.
TransactionManagementApplication.java
import org.springframework.boot.SpringApplication;
import
org.springframework.boot.autoconfigure.SpringBootApplication;
import
org.springframework.transaction.annotation.EnableTransactionM
anagement;
@SpringBootApplication
@EnableTransactionManagement
SpringApplication.run(TransactionManagementApplication.class,
args);
}
}
EmployeeService.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import
org.springframework.transaction.annotation.Transactional;
import
com.geeksforgeeks.transactionmanagement.model.Address;
import
com.geeksforgeeks.transactionmanagement.model.Employee;
import
com.geeksforgeeks.transactionmanagement.repository.Employee
Repository;
@Service
@Autowired
@Autowired
@Transactional
Employee employeeSavedToDB =
this.employeeRepository.save(employee);
address.setId(123L);
address.setAddress("Varanasi");
address.setEmployee(employee);
// of AddressService class
this.addressService.addAddress(address);
return employeeSavedToDB;
As we can see in the above media file, this time the employee data do not
get stored in the database, nor did the address data. This way the spring
has handled the transaction that both employees and address data gets
stored or no data gets stored.
Conclusion
1. Flat Transactions
Example:
BEGIN;
COMMIT;
2. Nested Transactions
Characteristics:
Example:
Parent Transaction:
- Start
- Debit account
Child Transactions:
- Transfer 1
- Transfer 2
3. Distributed Transactions
Definition: A transaction spanning multiple databases, systems, or
services.
Characteristics:
Example:
o Booking a vacation:
4. Chained Transactions
Characteristics:
Example:
o A shipment system:
5. Compensating Transactions
Characteristics:
Example:
o If an order cancellation occurs after the payment is processed,
a refund is initiated as compensation.
6. Long-Running Transactions
Characteristics:
Example:
7. Savepoint Transactions
Characteristics:
Example:
BEGIN;
SAVEPOINT sp1;
COMMIT;
8. Multi-Level Transactions
Characteristics:
o Provides flexibility in managing the relationships between sub-
transactions.
Example:
9. Read-Only Transactions
Definition: Transactions that only read data and do not modify it.
Characteristics:
Example:
o BEGIN;
o COMMIT;
Explicit Transactions:
o Example:
o BEGIN TRANSACTION;
o COMMIT;
Implicit Transactions:
o Example:
Characteristics:
Example:
Characteristics:
Real-World Examples
Compensating
Refunding a customer after order cancellation.
Transactions
Let me know if you'd like a deeper dive into any specific type!
What is a Transaction?
Example:
ACID Properties
1. Atomicity:
2. Consistency:
3. Isolation:
4. Durability:
o Ensures that the changes made by a completed transaction
are permanently saved in the database, even if a system
failure occurs.
Types of Transactions
1. Flat Transactions:
2. Nested Transactions:
3. Distributed Transactions: