JPA / Hibernate Spring @Transactional与JOIN FETCH

问题描述 投票:0回答:1

我面临着LazyInitializationException的有趣解决方案。为了防止这种情况(在OneToMany或ManyToMany上),一种已知的解决方案是使用JOIN FETCH查询。您可以看到以下几个例子之一: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,以封装此解决方案。那么,这两种解决方案的优缺点在哪里?

java spring hibernate jpa lazy-initialization
1个回答
1
投票

我们需要在这里解开几件事。

  1. @@ Transactional意味着Spring确保打开数据库连接(+事务)并再次关闭它。就这样。
  2. [当您选择一个包含惰性字段的实体时,您实际上是在说:我正在从我的实体中选择“一些”字段,除了惰性字段。
  3. 但是,如果以后由于需要在视图中访问它(.html,.ftl,.jsp等),则需要该惰性字段,则需要对数据库进行另一个选择以获取它。
  4. 问题:到那时,如果您是@Transactional方法的[[外部,则不再有数据库连接打开,因此没有LazyInitException。
  5. 总结:您的提取确保对所有数据发出1 select。如果您不这样做,则需要一个开放的数据库连接/事务,@ Transactional为您提供此连接。
  • 推荐:您应该尝试使用适当的JPQL / Criteria / SQL语句获取呈现视图所需的所有数据,而不要过多地依赖重新选择惰性字段。

  • © www.soinside.com 2019 - 2024. All rights reserved.