使用JPA和Spring Data JPA限制查询结果


1.简介

在本教程中,我们将学习如何使用JPA和Spring Data JPA 限制查询结果。

首先,我们将查看要查询的表以及要重现的SQL查询。

然后我们将直接探讨如何使用JPA和Spring Data JPA实现这一目标。

让我们开始吧!

2.测试数据

下面我们将在本文中查询表格。

我们想要回答的问题是,“首先占用的座位是什么,占用者是谁?”。

名字 座位号
吉尔 工匠 50
前夕 杰克逊 94
弗雷德 布罗格斯 22
瑞奇 博比 36
思雅 Kolisi 85

3. SQL

使用SQL,我们可能会编写一个类似于下面的查询:

SELECT firstName, lastName, seatNumber FROM passengers ORDER BY seatNumber LIMIT 1;

4. JPA设置

使用JPA,我们首先需要一个实体来映射我们的表:

@Entity
class Passenger {

    @Id
    @GeneratedValue
    @Column(nullable = false)
    private Long id;

    @Basic(optional = false)
    @Column(nullable = false)
    private String fistName;

    @Basic(optional = false)
    @Column(nullable = false)
    private String lastName;

    @Basic(optional = false)
    @Column(nullable = false)
    private int seatNumber;

    // constructor, getters etc.
}

接下来我们需要一个封装查询代码的方法,在此实现为PassengerRepositoryImpl#findOrderedBySeatNumberLimitedTo(int limit):

@Repository
class PassengerRepositoryImpl {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public List<Passenger> findOrderedBySeatNumberLimitedTo(int limit) {
        return entityManager.createQuery("SELECT p FROM Passenger p ORDER BY p.seatNumber",
          Passenger.class).setMaxResults(limit).getResultList();
    }
}

在我们的存储库方法中,我们使用EntityManager创建一个Query,我们在其上调用 setMaxResults()方法。

对Query#setMaxResults的这一调用最终将导致将limit语句附加到生成的SQL:

select
  passenger0_.id as id1_15_,
  passenger0_.fist_name as fist_nam2_15_,
  passenger0_.last_name as last_nam3_15_,
  passenger0_.seat_number as seat_num4_15_
from passenger passenger0_ order by passenger0_.seat_number limit ?

5.使用Spring Data JPA

我们也可以使用Spring Data JPA生成SQL。

5.1。first or top

我们可以采用的一种方法是使用方法名称派生,使用关键字first或top。

我们可以选择将数字指定为将返回的最大结果大小。如果我们省略它,Spring Data JPA假设结果大小为1。

记住我们想知道什么是第一个占用的座位以及谁占用它,我们可以通过以下两种方式省略它的数量:

Passenger findFirstByOrderBySeatNumberAsc();
Passenger findTopByOrderBySeatNumberAsc();

如果我们限制为一个实例结果,如上所述,那么我们也可以使用Optional包装结果:

Optional<Passenger> findFirstByOrderBySeatNumberAsc();
Optional<Passenger> findTopByOrderBySeatNumberAsc();

如果我们看一看的默认实现JpaRepository, 该 SimpleJpaRepository, 我们可以看到,它也要求查询#setMaxResults:

protected <S extends T > Page < S > readPage(TypedQuery < S > query,
  Class < S > domainClass, Pageable pageable,
  @Nullable Specification < S > spec) {
    if (pageable.isPaged()) {
        query.setFirstResult((int) pageable.getOffset());
        query.setMaxResults(pageable.getPageSize());
    }

    return PageableExecutionUtils.getPage(query.getResultList(), pageable, () -> {
        return executeCountQuery(this.getCountQuery(spec, domainClass));
    });
}

5.3。Comparison

这两种替代方案都将产生我们追求的SQL:

select
  passenger0_.id as id1_15_,
  passenger0_.fist_name as fist_nam2_15_,
  passenger0_.last_name as last_nam3_15_,
  passenger0_.seat_number as seat_num4_15_
from passenger passenger0_ order by passenger0_.seat_number asc limit ?

With first and top favoring convention and Pageable favoring configuration.