Spring 数据 - 实体未更新
Spring data - entity not updated
我有一个实体 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);
我不明白为什么会打印:Customer(id=1, name=John, surname=Smith).
据我所知,Hibernate 使用 dirty checking
机制来更新持久状态的实体。所以更改后的姓氏应该在事务结束时传播到数据库(但它不会 - 即使我将这段代码分成两个 @Transactional
方法)。难道我做错了什么?我真的需要在每次更改后手动 save
反对吗?为什么数据库中的姓氏字段没有更新?
@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
(假设基础交易 auto-commit,最有可能是这种情况):
- 您在一次交易中保存实体
- 使用 findCustomerByName 重新加载它,但它会立即分离
- 您修改分离的实体 - 不保存
- 您在另一笔交易中重新加载条目,但没有看到您的更新
我有一个实体 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);
我不明白为什么会打印:Customer(id=1, name=John, surname=Smith).
据我所知,Hibernate 使用 dirty checking
机制来更新持久状态的实体。所以更改后的姓氏应该在事务结束时传播到数据库(但它不会 - 即使我将这段代码分成两个 @Transactional
方法)。难道我做错了什么?我真的需要在每次更改后手动 save
反对吗?为什么数据库中的姓氏字段没有更新?
@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
(假设基础交易 auto-commit,最有可能是这种情况):
- 您在一次交易中保存实体
- 使用 findCustomerByName 重新加载它,但它会立即分离
- 您修改分离的实体 - 不保存
- 您在另一笔交易中重新加载条目,但没有看到您的更新