简体   繁体   中英

Spring JPA Many To Many Relationship Slow Loading

I have two models - Product and Category. There is a relation between them - m:n. How I defined the relation at the Product side:

@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;

When I try to load only one record ( findById ) it sends only one SQL Query and it's what I want to achieve. But when I request to load more than one it sends different SQL Query for every single product. How can I fix that problem? Should I write my own SQL Query (using EntityManager)?

Using EntityManager you can use LEFT JOIN FETCH to overcome the SELECT N+1 issue.

@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===

Strangely enough, using the same query with @Query returning Page<T> results in exception:

@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 ...

However using a List<T> it works fine but then I need to handle pagination manually.

@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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM