I have an entity Customer
and Spring data interface CustomerRepository
shown below:
public interface CustomerRepository extends JpaRepository<Customer,Long> {
Customer findCustomerByName(String name);
}
I save Customer
object in the database and then update one field like this:
customerRepository.save(new Customer("John", "Smith"));
Customer john = customerRepository.findCustomerByName("John");
john.setSurname("Barton");
customerRepository.flush();
customerRepository.findAll().forEach(System.out::println);
I don't understand why it prints: Customer(id=1, name=John, surname=Smith).
As far as I know, Hibernate uses dirty checking
mechanism to update entities in persistent state. So changed surname should be propagated to the database during end of transaction (but it does not - even if I separate this code into two @Transactional
methods). Am I doing something wrong? Do I really need to save
object manually after each change? Why surname field is not updated in the database?
@RunWith(SpringRunner.class)
@SpringBootTest
public class CustomerRepoTest {
@Autowired
private CustomerRepository customerRepository;
@Test
//NOTE: No @Transactional
public void testSaveFails() throws Exception {
customerRepository.save(new Customer("John", "Smith"));
Customer john = customerRepository.findCustomerByName("John");
john.setSurname("Barton");
customerRepository.flush();
customerRepository.findAll().forEach(System.out::println);
}
@Test
@Transactional
public void testSaveWorks() throws Exception {
customerRepository.save(new Customer("John", "Smith"));
Customer john = customerRepository.findCustomerByName("John");
john.setSurname("Barton");
//customerRepository.flush(); Flush is not necessary
customerRepository.findAll().forEach(System.out::println);
}
}
To explain: Hibernate keeps a cache of objects it loaded during a transaction. When a find method is executed, the id of a newly loaded object is compared to the id of the object in this cache, if found, the cached version is used.
@Transactional
works. If you miss the @Transactional
(assuming auto-commit on the underlying transaction, which is most likely the case):