我有一个实体Customer
和Spring数据接口CustomerRepository
,如下所示:
public interface CustomerRepository extends JpaRepository<Customer,Long> {
Customer findCustomerByName(String name);
}
我将Customer
对象保存在数据库中,然后像这样更新一个字段:
customerRepository.save(new Customer("John", "Smith"));
Customer john = customerRepository.findCustomerByName("John");
john.setSurname("Barton");
customerRepository.flush();
customerRepository.findAll().forEach(System.out::println);
我不明白为什么打印:客户(id = 1,姓名= John,姓氏= 史密斯)。
据我所知,Hibernate使用dirty checking
机制来更新持久状态的实体。因此,在事务结束时应该将更改的姓氏传播到数据库(但它不会 - 即使我将此代码分成两个@Transactional
方法)。难道我做错了什么?每次更改后我是否真的需要手动save
对象?为什么在数据库中没有更新姓氏字段?
答案 0 :(得分:0)
@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);
}
}
解释: Hibernate保留了在事务期间加载的对象的缓存。 执行find方法时,将新加载的对象的id与此缓存中对象的id进行比较,如果找到,则使用缓存版本。
@Transactional
版本的原因。 如果您错过@Transactional
(假设基础交易的自动提交,最有可能的话):