java - 如何避免覆盖实体中的数据
问题描述
我确实对 jpa 如何工作以及如何避免困扰我的一种情况有疑问。
好的,让我从简单的片段开始。
@GetMapping("/")
public List<Employee> index() {
Employee employee1 = employeeRepository.findById(1L).get();
Employee employee2 = ovewrite(employee1);
Employee employee3 = employeeRepository.findById(1L).get();
return Arrays.asList(employee1, employee2, employee3);
}
private Employee ovewrite(Employee employee){
employee.setFirstName("Test");
return employee;
}
如您所见,我创建了一些代码来测试使用id == 1
. 我确实employee1
从 db 获得,将其传递给ovewrite
刚刚更改的方法,firstName
之后我确实从 db 获得了同一个员工。
我在这里不明白的是,即使没有对数据库进行此更改的提交,employee3 也会更改名称。我想 jpa 正在缓存这些数据,并且对于这个对象的每个新find
对象,我们都会得到修改的记录?
还有一个问题,我怎样才能避免这种情况?因为我确实有一个带有这种“错误”的项目。对我来说,解决这个问题的最简单方法就是禁止这个同步化的孩子。
[编辑] 所以我试图通过find
在新事务内部调用来避免这个缓存“问题”。但是,我的employee3 仍然更改了名称属性。
@GetMapping("/")
public List<Employee> index() {
Employee employee1 = employeeRepository.findById(1L).get();
ovewrite(employee1);
Employee employee3 = newTxFind();
return Arrays.asList(employee1, employee3);
}
private Employee ovewrite(Employee employee){
employee.setFirstName("Test");
return employee;
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Employee newTxFind(){
return employeeRepository.findById(1L).get();
}
解决方案
实际上emplyee1 和employee3 将是同一个对象,这与JPA 缓存有关。所有 JPA 实现都至少具有 1 级缓存,即会话/事务缓存。您可以通过以下方式确认:
System.out.println(System.identityHashCode(employee1));
System.out.println(System.identityHashCode(employee3));
请注意,findById(1L) 返回的对象仅对于当前 JPA 事务是“相同的”。如果同时从另一个线程并行执行相同的 findById(1L),则 findById(1L) 的输出将是不同的对象。如果由于某种原因您从注释的方法中调用 findById(1L) 也是如此(您将收到不同的对象)
@javax.transaction.Transactional(REQUIRES_NEW)
或通过
@org.springframework.transaction.annotation.Transactional(propagation = Propagation = REQUIRES_NEW)
如果您想在修改employee1 对象时避免更改数据库,您可以将其从会话中分离,如果这是您真正需要的。分离的对象稍后可以重新连接,但有一些警告,很可能有更好的解决方法。
推荐阅读
- python - 在 Python 中格式化 JSON 数据
- android - 您如何通过即时应用程序中的意图共享图像?
- visual-studio - 使用 Visual Studio 处理源代码中的制表符或空格的默认设置?
- python-3.x - Python 数组舍入
- php - 如何使用php将日期插入mysql查询?
- python - PyTorch 二进制分类 - 相同的网络结构,“更简单”的数据,但性能更差?
- angular - 如何防止垫子扩展面板关闭?
- php - 做对了一切之后,Laravel 没有安装
- docker - 如何从撰写入口点拆分 curl 和 npm 命令
- yii2 - 如何在迁移中设置主键的初始值?