如何避免Hibernate出现“由于启用了“在集合获取上分页失败”错误?

如何避免Hibernate出现“由于启用了“在集合获取上分页失败”错误?,hibernate,rest,spring-data-jpa,spring-data,Hibernate,Rest,Spring Data Jpa,Spring Data,我试图在数据库中查询表产品的前5个元素,然后在Spring数据中使用Pageable查询下5个元素。但是我的表产品包含与另一个名为Company的表的关系,因此我也需要执行连接获取来获取公司信息 我的错误失败,因为启用了“在集合获取上分页失败”。我想我理解它为什么会出现这个错误,因为我无法对查询执行连接获取以放入页面,因为这可能包含数百万行 不管怎样,我正在学习这些技术,我正在寻找一种方法使其发挥作用。如果我将查询结果放在产品页面中,如何获取公司信息 以下是我在ProductRepository

我试图在数据库中查询表产品的前5个元素,然后在Spring数据中使用Pageable查询下5个元素。但是我的表产品包含与另一个名为Company的表的关系,因此我也需要执行连接获取来获取公司信息

我的错误失败,因为启用了“在集合获取上分页失败”。我想我理解它为什么会出现这个错误,因为我无法对查询执行连接获取以放入页面,因为这可能包含数百万行

不管怎样,我正在学习这些技术,我正在寻找一种方法使其发挥作用。如果我将查询结果放在产品页面中,如何获取公司信息

以下是我在ProductRepository.java中的操作方法:

@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {

    @Query(value = "select distinct product from Product product left join fetch product.companies",
        countQuery = "select count(distinct product) from Product product")
    Page<Product> findAllWithEagerRelationships(Pageable pageable);
}
在我的productResource.java中:

@GetMapping("/products")
public List<Product> getAllProducts(@RequestParam(required = false, defaultValue = "false") boolean eagerload,
                                        @RequestParam(required = false, defaultValue = "0") int limit,
                                        @RequestParam(required = false, defaultValue = "0") int offset) {
    log.debug("REST request to get all Products");

    if (limit != 0) {
        return productRepository.findAllWithEagerRelationships(PageRequest.of(offset,limit)).getContent();
    } else {
        return productRepository.findAllWithEagerRelationships();
    }
}
My Product.java包含:

@ManyToMany
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@JoinTable(name = "product_company",
           joinColumns = @JoinColumn(name = "product_id", referencedColumnName = "id"),
           inverseJoinColumns = @JoinColumn(name = "company_id", referencedColumnName = "id"))
private Set<Company> companies = new HashSet<>();

好的,多亏了SternK的评论,我发现,仅仅禁用hibernate.query.fail_on_pagination_over_collection_fetch设置可能不是一个好主意。因此,在一篇链接文章中,我尝试用两个SQL查询修复Hibernate错误,这两个SQL查询可以以读写模式获取实体

下面是我如何使用Spring存储库完成的:

@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {

    @Query(value = "select product.id from Product product order by product.id",
                countQuery = "select count(product.id) from Product product")
    Page<Long> getProductIds(Pageable pageable);

    @Query(value = "select distinct product from Product product left join fetch product.companies where product.id in (:listProducts) order by product.id",
            countQuery = "select count(distinct product) from Product product")
    List<Product> findAllProducts(@Param("listProducts") List<Long> listProducts);
}
因此,我在一个列表中捕获第一个查询getProductId的结果,并将此列表作为第二个查询findAllProducts的参数传递


希望它能帮助其他人:

看看这个,谢谢。工作得很好,我不需要用我的大脑去想它-
@RestController
@RequestMapping("/api")
@Transactional
public class ProductResource {

    private final ProductRepository productRepository;

    @GetMapping("/products")
    public List<Product> getAllProducts(@RequestParam(required = false, defaultValue = "false") boolean eagerload,
                                        @RequestParam(required = false, defaultValue = "0") int limit,
                                        @RequestParam(required = false, defaultValue = "0") int offset) {
        log.debug("REST request to get all Products");

        List<Long> productIds = productRepository.getProductIds(PageRequest.of(offset,limit, Sort.by("id").ascending())).getContent();
        return productRepository.findAllProducts(productIds);
    }
}