使用Spring Data JPA按日期和时间查询实体


1.简介

在这个快速教程中,我们将看到如何使用Spring Data JPA按日期查询实体。

我们将首先回忆一下如何使用JPA映射日期和时间。

然后,我们将创建一个包含日期和时间字段的实体以及一个Spring Data存储库来查询这些实体。

2.用JPA映射日期和时间

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

  • A date only
  • A time only
  • Or both

除了(optional)@Column annotation,我们还需要添加 @Temporal annotation 指定字段所代表的内容。

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

  • TemporalType.DATE
  • TemporalType.TIME
  • TemporalType.TIMESTAMP

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

3.In Practice

实际上,一旦我们的实体被正确设置,使用Spring Data JPA查询它们就没有太多工作要做。我们只需要使用查询方法@Query annotation。

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

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

3.1。Set Up an Entity

对于初学者,假设我们有一个 文章实体,具有发布日期,发布时间和创建日期和时间:

@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 which retrieves articles published on a given date
  • findAllByPublicationTimeBetween which retrieves articles published between two given hours
  • and findAllWithCreationDateTimeBefore which retrieves articles created before a given date and time

第一种方法依赖于Spring Data 查询方法机制,最后一种方法依赖于Query annotation。

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

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

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));
    }
}

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