如何使用 Hibernate 解决错误“失败,因为启用了'在集合获取上的分页失败'已启用”?
Posted
技术标签:
【中文标题】如何使用 Hibernate 解决错误“失败,因为启用了\'在集合获取上的分页失败\'已启用”?【英文标题】:How to get around the error "Failing because 'fail on pagination over collection fetch' is enabled" with Hibernate?如何使用 Hibernate 解决错误“失败,因为启用了'在集合获取上的分页失败'已启用”? 【发布时间】:2021-03-05 10:38:11 【问题描述】:我正在尝试使用Pageable
在 Spring Data 中查询我的数据库中我的表“产品”的前 5 个元素(然后是下一个等)。但是我的表“产品”包含与另一个名为“公司”的表的关系,所以我需要做一个join fetch
来获取公司信息。
我有错误Failing because 'fail on pagination over collection fetch' is enabled
。我想我明白它为什么会出现这个错误,这是因为我无法在查询中执行 join fetch
以输入 Page
,因为这可能包含数百万行。
无论如何,我正在学习这些技术,并且正在寻找一种让它发挥作用的方法。如果我将查询结果放在页面中的“产品”上,如何获取公司信息?
这是我在 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);
在我的 ProductRessource.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();
我的 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<>();
【问题讨论】:
看到这个article 【参考方案1】:好的,多亏了 SternK 的评论,我发现禁用 hibernate.query.fail_on_pagination_over_collection_fetch
设置可能不是一个好主意。所以as mentioned 在链接的文章中,我尝试使用两个可以在读写模式下获取实体的 SQL 查询来修复 Hibernate 错误。
这是我使用 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);
我有两个@Query
。在第一个中,我只选择 id 并将它们放入 Page<Long>
。在第二个中,我对我的公司执行 left join fetch
并通过 @Param("listProducts)
注释传递产品 ID 列表。
在我的 REST 控制器中,我有这个:
@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);
因此,我在 List<Long>
中捕获了第一个查询 (getProductIds
) 的结果,并将此列表作为第二个查询 (findAllProducts
) 的参数传递。
希望它对其他人有所帮助:)
【讨论】:
谢谢。效果很好,我不需要用我的大脑来弄清楚。 :-)【参考方案2】:谢谢@Nicryc
我添加这部分是因为我需要分页而不是列表。
@GetMapping("/products")
public Page<Product> getAllProducts(@RequestParam(required = false, defaultValue = "false") boolean eagerload,
Pageable pageable)
log.debug("REST request to get all Products");
Page<Long> productIds = productRepository.getProductIds(pageable);
List<Product> list = productRepository.findAllProducts(productIds.getContent());
return new PageImpl<>(list, pageable, list.size());
【讨论】:
以上是关于如何使用 Hibernate 解决错误“失败,因为启用了'在集合获取上的分页失败'已启用”?的主要内容,如果未能解决你的问题,请参考以下文章
如何解决“连接尝试失败,因为连接方在一段时间后没有正确响应......”错误?
Spring Data / Hibernate使用的错误列名