Trying out doing update Queries in Spring Data JPA. In my test method (see below) I'm saving one student with firstName="Bill" and lastName="Smith". How can it be that I'm getting "Bill" printed out to the console (very last line), given that studentRespository.findByFirstName("John") actually gives a list with one member? Any help appreciated...
@Modifying(flushAutomatically = true)
@Transactional
@Query("update Student s set s.firstName = ?1 where s.lastName= ?2")
public void updateFirstNameByLastName(String firstName, String lastName)
@Test
public void updateStudentFirstNameByLastName() {
studentRepository.save(student); //student.firstName="Bill", student.lastName="Smith"
studentRepository.updateFirstNameByLastName("John", "Smith");
List<Student> studentList = studentRepository.findByFirstName("John"); // size 1
System.out.println(studentList.get(0).getFirstName()); // "Bill"
}
CodePudding user response:
I guess your test didn't commit anything to the database
Try to add @Rollback(value = false) to the test class may help
CodePudding user response:
According to the JPA’s entity lifecycle states save() method may not write your changes to database immediately.
Since we use @Modifying in update query, this triggers the query annotated to the method as an updating query instead of a selecting one.
Reason for above issue is, when we save(), the persistence context of this with outdated entities may still there after the execution of the modifying query. EntityManager
do not automatically clear it. If you wish the EntityManager
to be cleared/flushed automatically, you can set the @Modifying annotation’s clearAutomatically and flushAutomatically attribute to true. Check this official doc Modifying Queries.
clearAutomatically(true/false) - Defines whether we should clear the underlying persistence context after executing the modifying query. (Default -false)
flushAutomatically(true/false) - Defines whether we should flush the underlying persistence context before executing the modifying query. (Default -false)
Add this @Modifying(clearAutomatically = true, flushAutomatically = true) to the updateFirstNameByLastName
method as below.
@Modifying(clearAutomatically = true, flushAutomatically = true)
@Transactional
@Query("update Student s set s.firstName = ?1 where s.lastName= ?2")
public void updateFirstNameByLastName(String firstName, String lastName)