一、简介

 

在本快速教程中,我们将了解如何使用 Spring Data JPA 按日期查询实体。

首先,我们将回顾一下如何使用 JPA 映射日期和时间。然后我们将创建一个具有日期和时间字段的实体,以及一个用于查询这些实体的 Spring Data 存储库。

2. 使用 JPA 映射日期和时间

 

首先,我们将回顾一些关于使用 JPA 映射日期的理论。要知道的是,我们需要决定是否要表示:

  • 仅限日期
  • 只有一次
  • 或两者

除了(可选)  @Column注释之外,我们还需要添加 @Temporal 注释来指定字段表示的内容。

此注释接受一个参数,该参数是TemporalType 枚举的值:

 

  • 时间类型.DATE
  • 时间类型.TIME
  • 时间类型.TIMESTAMP

可以在此处找到有关使用 JPA 进行日期和时间映射的详细文章。

3. 在实践中

 

在实践中,一旦我们的实体设置正确,使用 Spring Data JPA 查询它们就不需要做太多工作了。我们只需要使用 查询方法@Query注解。

每个 Spring Data JPA 机制都可以正常工作

让我们看几个使用 Spring Data JPA 按日期和时间查询的实体示例。

3.1。设置实体

 

例如,假设我们有一个带有发布日期、发布时间和创建日期和时间的Article实体:

 

@Entity
public class Article {

    @Id
    @GeneratedValue
    Integer id;
 
    @Temporal(TemporalType.DATE)
    Date publicationDate;
 
    @Temporal(TemporalType.TIME)
    Date publicationTime;
 
    @Temporal(TemporalType.TIMESTAMP)
    Date creationDateTime;
}

出于演示目的,我们将发布日期和时间分成两个字段;这样我们就代表了三种时间类型。

3.2. 查询实体

 

现在我们的实体已经全部设置好了,让我们创建一个 Spring Data存储库来查询这些文章。

我们将使用几个 Spring Data JPA 特性创建三个方法:

public interface ArticleRepository 
  extends JpaRepository<Article, Integer> {

    List<Article> findAllByPublicationDate(Date publicationDate);

    List<Article> findAllByPublicationTimeBetween(
      Date publicationTimeStart,
      Date publicationTimeEnd);

    @Query("select a from Article a where a.creationDateTime <= :creationDateTime")
    List<Article> findAllWithCreationDateTimeBefore(
      @Param("creationDateTime") Date creationDateTime);

}

所以我们定义了三个方法:

  • findAllByPublicationDate检索在给定日期发布的文章
  • findAllByPublicationTimeBetween 检索在两个给定小时之间发布的文章
  • 和 findAllWithCreationDateTimeBefore检索在给定日期和时间之前创建的文章

前两个方法依赖于 Spring Data 的查询方法机制,最后一个依赖于@Query注解。

 

最后,这不会改变处理日期的方式。第一种方法将只考虑参数的日期部分。

第二种只会考虑参数的时间。最后一个将使用日期和时间。

3.3. 测试查询

 

我们要做的最后一件事是设置一些测试来检查这些查询是否按预期工作。

我们首先将数据导入我们的数据库,然后我们将创建一个测试类来检查存储库的每个方法:

@RunWith(SpringRunner.class)
@DataJpaTest
public class ArticleRepositoryIntegrationTest {

    @Autowired
    private ArticleRepository repository;

    @Test
    public void whenFindByPublicationDate_thenArticles1And2Returned() {
        List<Article> result = repository.findAllByPublicationDate(
          new SimpleDateFormat("yyyy-MM-dd").parse("2018-01-01"));

        assertEquals(2, result.size());
        assertTrue(result.stream()
          .map(Article::getId)
          .allMatch(id -> Arrays.asList(1, 2).contains(id)));
    }

    @Test
    public void whenFindByPublicationTimeBetween_thenArticles2And3Returned() {
        List<Article> result = repository.findAllByPublicationTimeBetween(
          new SimpleDateFormat("HH:mm").parse("15:15"),
          new SimpleDateFormat("HH:mm").parse("16:30"));

        assertEquals(2, result.size());
        assertTrue(result.stream()
          .map(Article::getId)
          .allMatch(id -> Arrays.asList(2, 3).contains(id)));
    }

    @Test
    public void givenArticlesWhenFindWithCreationDateThenArticles2And3Returned() {
        List<Article> result = repository.findAllWithCreationDateTimeBefore(
          new SimpleDateFormat("yyyy-MM-dd HH:mm").parse("2017-12-15 10:00"));

        assertEquals(2, result.size());
        assertTrue(result.stream()
          .map(Article::getId)
          .allMatch(id -> Arrays.asList(2, 3).contains(id));
    }
}

每个测试都会验证是否只检索到符合条件的文章。

4。结论

 

在这篇简短的文章中,我们学习了如何使用 Spring Data JPA 按日期和时间字段查询实体。

在使用 Spring Data 机制查询实体之前,我们讨论了一些理论。我们看到这些机制处理日期和时间的方式与处理其他类型数据的方式相同。

本文的源代码可在 GitHub 上获得。