当前位置: 首页 > 知识库问答 >
问题:

Spring Data JPA-谓词-使用分页连接获取-响应很慢

夏兴平
2023-03-14

我将spring datat jpa谓词与Join Fetch一起使用,我的响应非常慢。我收到一条警告消息:

[警告]组织。冬眠hql。内部的ast。QueryTranslatorImpl:hh000104:使用集合获取指定的firstResult/maxResults;正在内存中应用!

共有1个答案

齐雅畅
2023-03-14

您可以使用基于双查询方法的通用/可重用方法。

一个SQL查询用于检索实体的ID,另一个查询使用包含第二个查询中ID的IN谓词。

实现一个自定义的Spring Data JPA执行器:

@NoRepositoryBean
public interface AsimioJpaSpecificationExecutor<E, ID extends Serializable> extends JpaSpecificationExecutor<E> {

  Page<ID> findEntityIds(Pageable pageable);
}


public class AsimioSimpleJpaRepository<E, ID extends Serializable> extends SimpleJpaRepository<E, ID>
        implements AsimioJpaSpecificationExecutor<E, ID> {

  private final EntityManager entityManager;
  private final JpaEntityInformation<E, ID> entityInformation;

  public AsimioSimpleJpaRepository(JpaEntityInformation<E, ID> entityInformation, EntityManager entityManager) {
    super(entityInformation, entityManager);
    this.entityManager = entityManager;
    this.entityInformation = entityInformation;
  }

  @Override
  public Page<ID> findEntityIds(Pageable pageable) {
    CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
    CriteriaQuery<ID> criteriaQuery = criteriaBuilder.createQuery(this.entityInformation.getIdType());
    Root<E> root = criteriaQuery.from(this.getDomainClass());

    // Get the entities ID only
    criteriaQuery.select((Path<ID>) root.get(this.entityInformation.getIdAttribute()));

    // Update Sorting
    Sort sort = pageable.isPaged() ? pageable.getSort() : Sort.unsorted();
    if (sort.isSorted()) {
      criteriaQuery.orderBy(toOrders(sort, root, criteriaBuilder));
    }

    TypedQuery<ID> typedQuery = this.entityManager.createQuery(criteriaQuery);

    // Update Pagination attributes
    if (pageable.isPaged()) {
      typedQuery.setFirstResult((int) pageable.getOffset());
      typedQuery.setMaxResults(pageable.getPageSize());
    }

    return PageableExecutionUtils.getPage(typedQuery.getResultList(), pageable,
      () -> executeCountQuery(this.getCountQuery(null, this.getDomainClass())));
  }

  protected static long executeCountQuery(TypedQuery<Long> query) {
    Assert.notNull(query, "TypedQuery must not be null!");

    List<Long> totals = query.getResultList();
    long total = 0L;

    for (Long element : totals) {
      total += element == null ? 0 : element;
    }

    return total;
  }
}

您的存储库类类似于:

@Repository
public interface FilmDao extends JpaRepository<Film, Integer>, AsimioJpaSpecificationExecutor<Film, Integer> {

  @EntityGraph(
    type = EntityGraphType.FETCH,
    attributePaths = {
      "language", 
      "filmActors", "filmActors.actor"
    }
  )
  List<Film> findAll(@Nullable Specification<Film> spec);

  @EntityGraph(
    type = EntityGraphType.FETCH,
      attributePaths = {
      "language", 
      "filmActors", "filmActors.actor"
    }
  )
  Page<Integer> findEntityIds(Pageable pageable);
}

您的@Service注释类可以执行以下操作:

public Page<Film> retrieveFilms(Pageable page) {
    // Getting film ids and page data to prevent:
    // HHH000104: firstResult/maxResults specified with collection fetch; applying in memory! 
    // which affects application's performance
    Page<Integer> filmIdsPage = this.filmDao.findEntityIds(page);

    List<Film> result;
    List<Integer> filmIds = filmIdsPage.getContent();
    if (CollectionUtils.isEmpty(filmIds)) {
      result = Lists.newArrayList();
    } else {
      // Retrieve films using IN predicate
      Specification<Film> fimlIdInSpecification = FilmSpecifications.idIn(Sets.newHashSet(filmIds));
      result = this.filmDao.findAll(fimlIdInSpecification);
    }
    return PageableExecutionUtils.getPage(result, page, () -> filmIdsPage.getTotalElements());
  }

你可以在https://tech.asimio.net/2021/05/19/Fixing-Hibernate-HHH000104-firstResult-maxResults-warning-using-Spring-Data-JPA.html

 类似资料:
  • 我正在使用Apache HTTPComponents(版本4.5.2),并试图通过代理服务器请求HTTPS页面。 编辑: 我的主要问题是,我需要知道如何区分代理服务器的故障和请求的URI的故障(对于HTTP和HTTPS)。我有很多代理,它们不是百分之百可靠的,所以在代理失败的情况下,我需要用不同的代理服务器重试请求。 例如(对于HTTPS),在这两种情况下都可以返回NoHttpResponseEx

  • 我使用查询DSL生成实体EntitySerializer,以便使用QueryDSL(与SpringData集成)查询JPA实体。

  • 有两个具有相同结构的地图,即map1和map2,其结构为

  • 问题内容: 我正在为我的第一个应用程序浏览本教程(学习Swift):http : //www.appcoda.com/search-bar-tutorial- ios7/ 我被困在这部分(Objective-C代码): 谁能建议如何在Swift中为NSPredicate创建等效项? 问题答案: 这实际上只是语法切换。好,所以我们有这个方法调用: 在Swift中,构造函数跳过“ blahWith…”

  • 我在我的swift应用程序中使用Moya进行网络请求。 我能够获得请求和映射结果使用Moya-Object Mapper。 我以前使用过alamofire,我熟悉如何进行post,获取请求和阅读响应头。 然而,我似乎无法理解我怎么能在莫亚也这样做。 我确实浏览了文档,但它没有说明任何关于读取响应头的内容。 有没有任何例子或教程,我可以遵循如何做一个HTTP身份验证和读取响应头。以及如何发出post

  • 有一个读入整数序列的语法,它的玄机是由输入的部分指定有多少个整数组合在一起,所以我们必须等到运行时才能知道有多少整数被匹配。这里是示例输入文件idata.txt的内容: 2 9 10 3 1 2 3 第1个数字表示匹配后续两个数字9和10;紧跟10的数字3表示匹配接下来的三个数字。我们的目的是设计一个语法IData.g,把9和10组合在一起,把1、2和3组合在一起。在语法上执行以下命令后显示的语