【发布时间】:2019-09-09 15:10:00
【问题描述】:
我有一个简单的控制器方法,在其中创建一个新对象Car,然后将其名称设置为Audi:
@GetMapping(value = "/resource")
public ResponseEntity visit() {
Car car = carRepo.save(new Car("VolksWagen")); // Car should be managed now?
car.setName("Audi"); // <-- has no effect on database state
return ResponseEntity.ok().build();
}
在数据库中,它永远不会变成Audi,而是保持VolksWagen。
为什么会这样?对于持久化上下文,新创建的Car 不应该处于托管 状态吗?
注意:如果我添加 @Transactional 注释,它会起作用。我认为如果启用 OSIV 就足够了。我对 OSIV 和 @Transactional 有什么误解?
【问题讨论】:
-
OSIV 让 session 保持打开状态,以便在呈现视图时能够延迟加载关联。但它不会让 transaction 处于打开状态。更改已经提交,并且以后的更改将不会保留,因为以后的更改会被刷新或提交(并且因为更改不应该首先发生)
-
OSIV 无论如何都是一个肮脏的黑客,因为事务提交后加载的数据可能与事务内部加载的数据不一致。我会避免它。 vladmihalcea.com/the-open-session-in-view-anti-pattern
-
@JBNizet 我的应用程序实际上只是一个 API,所以没有必要使用 OSIV。我以某种方式设法在脑海中将 OSIV 与
@Transactional混为一谈,但现在我明白它们是完全不同的东西。谢谢!
标签: jpa spring-data-jpa transactional open-session-in-view