Using @Modifying

Great! Now, let’s explore modifying queries using @Modifying in Spring Data JPA for updating and deleting records.


🎯 Learning Objectives

βœ… Learn how to use @Modifying for update and delete operations
βœ… Understand when to use @Transactional with modifying queries
βœ… Implement modifying queries in StudentRepository


πŸ”Ή Step 1: Update StudentRepository with Modifying Queries

Spring Data JPA allows modifying queries using @Modifying, usually combined with @Transactional.

package com.example.repository;

import com.example.model.Student;
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 StudentRepository extends JpaRepository<Student, Integer> {

    // Update student's email by ID
    @Modifying
    @Transactional
    @Query("UPDATE Student s SET s.email = :email WHERE s.id = :id")
    int updateEmailById(@Param("id") int id, @Param("email") String email);

    // Delete a student by ID
    @Modifying
    @Transactional
    @Query("DELETE FROM Student s WHERE s.id = :id")
    void deleteStudentById(@Param("id") int id);

    // Delete students by last name
    @Modifying
    @Transactional
    @Query("DELETE FROM Student s WHERE s.lastName = :lastName")
    int deleteStudentsByLastName(@Param("lastName") String lastName);
}

βœ… Why?

  • @Modifying tells Spring that the query modifies the database.
  • @Transactional ensures the operation is wrapped in a transaction.
  • The int return type gives the number of rows affected.

πŸ”Ή Step 2: Update StudentService to Call Modifying Queries

package com.example.service;

import com.example.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class StudentService {

    @Autowired
    private StudentRepository studentRepository;

    @Transactional
    public int updateStudentEmail(int id, String email) {
        return studentRepository.updateEmailById(id, email);
    }

    @Transactional
    public void removeStudentById(int id) {
        studentRepository.deleteStudentById(id);
    }

    @Transactional
    public int removeStudentsByLastName(String lastName) {
        return studentRepository.deleteStudentsByLastName(lastName);
    }
}

βœ… Why?

  • Methods wrap modifying queries for cleaner service logic.
  • Transactional methods ensure consistency when modifying data.

πŸ”Ή Step 3: Test in Main.java

package com.example;

import com.example.model.Student;
import com.example.service.StudentService;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Main {
    public static void main(String[] args) {
        SpringApplication.run(Main.class, args);
    }

    @Bean
    public CommandLineRunner demo(StudentService studentService) {
        return args -> {
            Student student = new Student("John", "Doe", "john.doe@example.com");
            studentService.saveStudent(student);

            // Update Email
            int updated = studentService.updateStudentEmail(student.getId(), "new.email@example.com");
            System.out.println("Updated " + updated + " student(s) email");

            // Delete by ID
            studentService.removeStudentById(student.getId());
            System.out.println("Student removed by ID");

            // Delete by Last Name
            int deleted = studentService.removeStudentsByLastName("Doe");
            System.out.println("Deleted " + deleted + " student(s) with last name Doe");
        };
    }
}

βœ… Why?

  • Saves a student, updates the email, and deletes students dynamically.
  • Confirms that modifying queries work as expected.

πŸ“Œ Key Takeaways

FeatureExplanation
@ModifyingMarks queries that modify data
@TransactionalEnsures updates/deletes run in a transaction
Return TypeReturns affected rows count (for updates/deletes)
@QuerySupports JPQL and Native SQL

πŸš€ Next Steps

βœ… Extend modifying queries to update multiple fields
βœ… Add logging to check before-and-after changes
βœ… Implement Spring REST API to trigger modifying queries

πŸ‘‰ Would you like to explore modifying multiple fields next? 😊