java - JPA / Hibernate Spring @Transactional 与 JOIN FETCH
问题描述
我正面临着有趣的 LazyInitializationException 解决方案。为了防止这种情况(在 OneToMany 或 ManyToMany 上),一种已知的解决方案是使用 JOIN FETCH Query。你可以看到她的几个例子之一:https ://thoughts-on-java.org/best-practices-for-many-to-many-associations-with-hibernate-and-jpa/
其他更简单的解决方案是使用 Spring 中的 @Transactional。例如像这样:
@DeleteMapping(value ="/product/{tagId}")
@ResponseBody
@Transactional
public String deleteProductWithoutRelation(@PathVariable String product, Model model) {
Optional<Product> pr = productService.selectProduct(product);
if (pr.isPresent()) {
tag.get().getCustomer().size(); //usualy throws LazyInitializationException,
//without JOIN-FETCH Statment or @Transactional
return deletedTagId;
}
当然,您可以将存储库服务中的某些方法的@Transactional 放置在此解决方案中。那么这两种解决方案有哪些优点或缺点呢?
解决方案
有几件事我们需要在这里解开。
- @Transactional 意味着 Spring 确保打开一个数据库连接(+ 事务)并再次关闭它。而已。
- 当您选择一个包含惰性字段的实体时,您实际上是在说:我正在从我的实体中选择“一些”字段,除了惰性字段。
- 但是,如果您稍后需要该惰性字段,因为您试图在视图(.html、.ftl、.jsp 等)中访问它,您需要向数据库发出另一个选择以获取它。
- 问题:此时,如果您不在@Transactional 方法之外,则不再打开数据库连接,因此会出现 LazyInitException。
- 总结一下:您的 fetch 确保为所有数据发出 1 个选择。如果你不这样做,你需要一个开放的数据库连接/事务,@Transactional 给你。
建议:您应该尝试使用适当的 JPQL/Criteria/SQL 语句获取渲染视图所需的所有数据,并且不要过多地依赖重新选择惰性字段。
推荐阅读
- javascript - UseSelector 传递 props
- sql - Snowflake SQL - 选择值包含至少一个字母的列的行
- qt - QMessage 框根据 IF 条件消失
- postgresql - postgresql_exporter 不工作。如何配置它?
- gradle - 如何在 Gradle 7 中抑制“执行优化已被禁用”警告?
- html - Primefaces:无法在 IE 的 inputTextarea 中选择文本
- java - Firebase Auth Anonymouse Registration/Login for Android java
- python - 如何将python accum函数与3d数组一起使用
- r - R中按日期的数据帧
- express - Mongoose await post.save() 似乎没有返回承诺