简体   繁体   中英

Spring Data JPA - JPQL update query - printing out unupdated value

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" }

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 .

Annotation Type Modifying

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)

I guess your test didn't commit anything to the database

Try to add @Rollback(value = false) to the test class may help

带有 JUnit 5 测试的 Spring Boot

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM