Spring JPA多对多关系缓慢加载

时间:2017-10-06 22:07:06

标签: mysql spring jpa spring-data-jpa

我有两个型号 - 产品和类别。他们之间有关系 - m:n。我如何在产品方面定义关系:

@JoinTable(
        name = "products_categories",
        joinColumns = @JoinColumn(
                name = "product_id",
                referencedColumnName = "id"
        ),
        inverseJoinColumns = @JoinColumn(
                name = "category_id",
                referencedColumnName = "id"
        )
)
@ManyToMany(fetch = FetchType.EAGER)
private Set<Category> categories;

当我尝试只加载一条记录(findById)时,它只发送一个SQL查询,这就是我想要实现的目标。但是当我请求加载多个时,它会为每个产品发送不同的SQL查询。我该如何解决这个问题?我应该编写自己的SQL查询(使用EntityManager)吗?

1 个答案:

答案 0 :(得分:0)

使用EntityManager,您可以使用LEFT JOIN FETCH来解决 SELECT N + 1 问题。

@Autowired EntityManager entityManager;

@Test
public void findWithEntityManager() {
    Query q = entityManager.createQuery("SELECT p FROM ProductEntity p LEFT JOIN FETCH p.categories");
    List<ProductEntity> prods = q.getResultList();
    prods.forEach(p -> { 
        System.out.println(p.getCategories().size());
    });
}
//Hibernate: select productent0_.id as id1_4_0_, ... from product productent0_ left outer join product_category categories1_ on productent0_.id=categories1_.ProductEntity_id left outer join category categoryen2_ on categories1_.categories_id=categoryen2_.id

<强> === EDIT ===

奇怪的是,使用@Query返回Page<T>的同一查询会导致异常:

@Query("SELECT p FROM ProductEntity p LEFT JOIN FETCH p.categories c")
Page<ProductEntity> findAllLeftJoin(Pageable pageable);
// Caused by: org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list ...

然而,使用List<T>它工作正常,但我需要手动处理分页。

@Query("SELECT p FROM ProductEntity p LEFT JOIN FETCH p.categories c")    
List<ProductEntity> findAllLeftJoin();
// Hibernate: productent0_.id as id1_4_0_,... from product productent0_ left outer join product_category categories1_ on productent0_.id=categories1_.ProductEntity_id left outer join category categoryen2_ on categories1_.categories_id=categoryen2_.id