Spring Data JPA 获取最后一条记录

1、概览

本文将带你了解使用 Spring Data JPA 获取最后一条记录的多种方式。

2、初始设置

首先,创建并初始化要查询的表。

创建一个 Post 实体类:

@Entity
public class Post {

    @Id
    private Long id;
    private String title;
    private LocalDate publicationDate;

    // get、set 方法

}

@Entity 表示注解的类代表数据库中的一个表。@Id 注解定义了主键。

为了简单起见,这里使用的是 H2 内存数据库。

添加一个基本的 SQL 脚本,创建 Post 类对应的 post 表:

DROP TABLE IF EXISTS post;
CREATE TABLE post(
    id INT PRIMARY KEY,
    title VARCHAR(200),
    publication_date DATE
)

接着,添加一些数据:

INSERT INTO post (id, title, publication_date) VALUES(1, 'Facebook post', '2020-11-10');
INSERT INTO post (id, title, publication_date) VALUES(2, 'Instagram post', '2020-12-24');
INSERT INTO post (id, title, publication_date) VALUES(3, 'Twitter post', '2023-01-10');
INSERT INTO post (id, title, publication_date) VALUES(4, 'tiktok post', '2023-03-18');
INSERT INTO post (id, title, publication_date) VALUES(5, 'Pinterest post', '2023-09-09');

如你所见,最后一条记录的 ID 是 5

3、使用查询方法

Spring Data JPA 支持派生查询方法,这个特性提供了一种方便的方式,可以根据方法名生成查询,而无需手动编写SQL语句。

Spring Data JPA 并不提供获取最后一条记录的直接方法,但它提供了从一组记录的起始位置检索数据的方法。

例如,可以使用 findFirst 前缀创建一个获取第一条记录的派生查询:

public interface PostRepository extends JpaRepository<Post, Integer> {

    Post findFirstByOrderByPublicationDateDesc();

}

方法名 findFirstByOrderByPublicationDateDesc() 的每个部分都有其意义。动词 find 告诉 Spring Data JPA 生成一个 select 查询,而 First 表示应从结果集中检索第一条记录。

此外,OrderByPublicationDateDesc 表示希望按照 publicationDate 属性对记录进行倒序排序。

Spring Data JPA 会智能地解析方法名称。首先,它会按 publicationDate 降序排列 post。这样,就会把最后一条记录放在结果的开头。

然后,它将 findFirst 解释为返回排序记录的第一个元素。结果就是,我们得到了表中的最后一条记录。

测试:

@Test
void givenPosts_whenUsingFindFirstDerivedQuery_thenReturnLastPost() {
    Post post = postRepository.findFirstByOrderByPublicationDateDesc();

    assertNotNull(post);
    assertEquals(5, post.getId());
}

上述测试会执行通过。

同样,也可以使用 findTop 关键字来实现相同的结果。可以交替使用 firstFirstfindTop,而不会出现任何问题:

Post findTopByOrderByPublicationDateDesc();

最后,为 findTopByOrderByPublicationDateDesc() 方法创建另一个测试用例:

@Test
void givenPosts_whenUsingFindTopDerivedQuery_thenReturnLastPost() {
    Post post = postRepository.findTopByOrderByPublicationDateDesc();

    assertNotNull(post);
    assertEquals(5, post.getId());
}

如上,测试用例成功通过。

4、使用 @Query 注解

另一种解决方案是使用 @Query 注解将方法绑定到可检索最后一条记录的查询中。默认情况下,@Query 接受 JPQL 查询。

PostRepository 中添加另一个名为 findLastPost() 的方法,并使用 @Query 来指定获取最后一条记录的查询:

@Query("SELECT p FROM Post p ORDER BY p.publicationDate DESC LIMIT 1")
Post findLastPost();

简而言之,这里按照 publicationDate 倒序 selectpost 记录,然后,使用 LIMIT 1 只检索一个 post。返回的 post 表示最后一条记录。

同样,添加一个测试用例来测试这个方法:

@Test
void givenPosts_whenUsingQueryAnnotation_thenReturnLastPost() {
    Post post = postRepository.findLastPost();

    assertNotNull(post);
    assertEquals(5, post.getId());
}

不出所料,最后一条记录的 ID 为 5。

5、总结

本文介绍了如何在 Spring Data JPA 中通过派生方法或者自定义 @Query 来实现检索数据表中的最后一条记录。


Ref:https://www.baeldung.com/spring-data-jpa-last-record