我有两个型号 - 产品和类别。他们之间有关系 - 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)吗?
答案 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