【问题标题】:Count Date in JPA or JPQL在 JPA 或 JPQL 中计算日期
【发布时间】:2019-10-16 23:40:04
【问题描述】:

我需要统计当月的注册用户数。 我使用原始方法

我使用 H2 数据库。

  1. 在模型(阅读器)中,我有一个字段:private String LocalDate 因为我将数据库中的日期保存为String:

    @Override
    public String getCurrentDate() {
        LocalDate localDate = LocalDate.now();
        DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String formatDate = localDate.format(format);
        return  formatDate;
    }
    
  2. 在 ReaderRepository 我有这个:

    Integer getCountDatesCurrentMonth();
    List<String> allDates();
    

在 List 中我从表中获取所有日期。

  1. ReaderServiceImpl我有这个方法:

    @Override
    public Integer getCurrentMonthRegisteredReaders() {
        List<String> dates = readerRepository.allDates();
        Integer date = LocalDate.now().getMonthValue();
        String s;
        int count=0;
    
        for(int i =0;i<dates.size();i++){
            s = dates.get(i).charAt(5)+""+dates.get(i).charAt(6);
            if(s.equals(date.toString()))
                count++;
        }
    
        return count;
    

我在哪里获得当月注册的用户数

代码运行完美,并在当月注册的读者的网页上显示我, 但我想用 JPA 或 JPQL 在一两行中做到这一点,但我做不到。

我尝试过使用 JPA,但不起作用:

Integer countByDateMonthValue(int currentMonth);

我得到错误:

 Caused by: java.lang.IllegalStateException: Illegal attempt to dereference path source           [null.date] of basic type

或使用 JPQL:

@Query("select count(date) from Reader where... ")

但我不知道该怎么办......

【问题讨论】:

    标签: jpa spring-data-jpa jpql


    【解决方案1】:

    这里的挑战是 JPQL 没有定义很多有用的方法来操作日期。因此查询将取决于您的 JPA 实现(可能是 Hibernate 或 EclipseLink)或您正在使用的数据库或两者兼而有之。

    这个应该和 Hibernate 一起工作

    @Query("select count(date) from Reader r where month(r.date) = :month")
    int countForMonth(int month);
    

    这个应该和Oracle一起工作

    @Query("select count(date) from Reader r where EXTRACT(month FROM r.date) = :month", nativeQuery = true)
    int countForMonth(int month);
    

    或者,如果您总是希望以当前月份为基础

    @Query("select count(date) from Reader r where EXTRACT(month FROM r.date) = EXTRACT(month FROM sysdate)", nativeQuery = true)
    int countForMonth();
    

    您当前的逻辑和上面的查询忽略了年份,因此如果月份匹配,所有年份的行都会被计算在内。 如果您真的只希望计算当前月份的行,或者如果您有来自单行的行并不重要,您可以使用 SpEL 表达式创建日期范围。 您可以注册提供当前月份开始和结束的自定义函数,并在查询中执行以下操作:

    @Query("select count(date) from Reader r where r.date between :#{startOfMonth(month)} and :#{endOfMonth(month)}")
    int countForMonth(int month);
    

    在查询中查看此blog article how to use SpEL expressions 以及如何将自定义扩展注册到评估上下文。

    【讨论】:

      【解决方案2】:

      完成。 我做了这个选择,效果很好。现在我不需要发送 LocalDate().now().getMonthValue 作为我方法中的参数。

           @Query(value = "select count(date) from Reader r where  extract(month from r.date) = extract(month from sysdate)" +
                      "and extract(year from r.date) = extract(year from sysdate)",nativeQuery = true)
              int findAllByMonth();
      

      Danke Schön Jens Schauder !

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-01-14
        • 2017-12-24
        • 2011-02-23
        • 2015-11-29
        • 2014-09-19
        • 2016-03-21
        • 2011-06-16
        相关资源
        最近更新 更多