Using @Modifying and @Transactional in Spring JPA

1 min read

Using @Modifying and @Transactional in Spring JPA

Spring Data JPA provides powerful annotations like @Modifying and @Transactional to perform update and delete operations efficiently. These annotations allow modifying queries in a structured and transactional manner.

Understanding @Modifying and @Transactional

@Modifying

The @Modifying annotation is used in conjunction with @Query to indicate that a query modifies the database (i.e., update, delete, or insert operations). It signals that the method does not return an entity but instead affects the database state.

@Transactional

The @Transactional annotation is used to ensure that database operations occur within a transaction. It helps maintain data consistency and rollback changes in case of errors.

Example: Using @Modifying and @Transactional

Step 1: Add Dependencies

Ensure you have the necessary dependencies in your pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

Step 2: Define the Entity

Create an entity class to map to the database table.

import jakarta.persistence.*;

@Entity
@Table(name = "employees")
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String department;
    private double salary;

    // Getters and Setters
}

Step 3: Define the Repository

Use @Modifying and @Transactional annotations to create update and delete operations.

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
    
    @Modifying
    @Transactional
    @Query("UPDATE Employee e SET e.salary = :salary WHERE e.id = :id")
    int updateEmployeeSalary(@Param("id") Long id, @Param("salary") double salary);
    
    @Modifying
    @Transactional
    @Query("DELETE FROM Employee e WHERE e.id = :id")
    int deleteEmployeeById(@Param("id") Long id);
}

Step 4: Implement the Service Layer

The service layer calls the repository methods and ensures transactional behavior.

import org.springframework.stereotype.Service;
import java.util.Optional;

@Service
public class EmployeeService {
    private final EmployeeRepository employeeRepository;

    public EmployeeService(EmployeeRepository employeeRepository) {
        this.employeeRepository = employeeRepository;
    }

    public int updateSalary(Long id, double salary) {
        return employeeRepository.updateEmployeeSalary(id, salary);
    }
    
    public int deleteEmployee(Long id) {
        return employeeRepository.deleteEmployeeById(id);
    }
}

Step 5: Create the REST Controller

Expose the update and delete methods through REST endpoints.

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/employees")
public class EmployeeController {
    private final EmployeeService employeeService;

    public EmployeeController(EmployeeService employeeService) {
        this.employeeService = employeeService;
    }

    @PutMapping("/updateSalary/{id}/{salary}")
    public int updateSalary(@PathVariable Long id, @PathVariable double salary) {
        return employeeService.updateSalary(id, salary);
    }
    
    @DeleteMapping("/delete/{id}")
    public int deleteEmployee(@PathVariable Long id) {
        return employeeService.deleteEmployee(id);
    }
}

Testing the Application

Run the application and test the API calls:

  1. Update Employee SalaryPUT /employees/updateSalary/1/75000
  2. Delete Employee by IDDELETE /employees/delete/1

Conclusion

The @Modifying annotation in Spring JPA allows executing update and delete queries efficiently. Pairing it with @Transactional ensures that operations are executed safely within a transaction, maintaining data integrity. By following this approach, developers can seamlessly integrate database modification operations into their Spring Boot applications.

🤞 Never miss a story from us, get weekly updates to your inbox!