【问题标题】:HQL to query records between two datesHQL查询两个日期之间的记录
【发布时间】:2014-02-11 11:03:11
【问题描述】:

我试图在我的 Spring/Hibernate 应用程序中使用 HQL 查询所有客户记录,这些客户记录的 DateAdded 在 Date1 和 Date2 之间或 LastSeen 在 Date1 和 Date2 之间,所以我在 Repository/DAO 类中构建了这个 HQL 查询:

sessionfactory.getCurrentSession().createQuery("from Customer c where c.dateAdded BETWEEN '"+startDate+"' AND '"+endDate+"' OR c.lastSeenDate BETWEEN  '"+startDate+"' AND '"+endDate+"'").list();

我已调试应用检查 startDate 和 endDate 并发现它们发送为:

开始日期:2014 年 1 月 22 日星期三 01:16:57 HKT

结束日期:2014 年 1 月 29 日星期三 01:16:57 HKT

在 DB 中,我 100% 确定至少有一条记录满足此查询,因为这条记录 DateAdded 和 LastSeen 如下:

2014-01-23 15:33:38

2014-01-25 15:33:38

那么有人可以告诉我我做错了什么/在这里失踪了吗?

【问题讨论】:

  • 我不确定当日期作为文本传递时如何在 HQL 中处理时区,但您应该真的使用查询参数而不是字符串连接。
  • @Guillaume 是专门或一般来说解决这个问题的?
  • @Guillaume 将其更改为 sessionfactory.getCurrentSession().createQuery("from Customer c where c.dateAdded BETWEEN :startD AND :endD").setParameter("startD", startDate).setParameter(" endD", startDate).list();还是不行:(
  • @Mchan from Customer where dateAdded >= :startD and dateAdded <= :endD 怎么样?我一直在使用类似的语法,它工作正常。如果这也不起作用,那么可能还有其他问题。
  • @AdrianShum 试过了,我尝试传递数据库中格式化的日期,但它不会接受,因为在我传递字符串时参数期望日期。

标签: spring hibernate hql


【解决方案1】:

您需要使用@JsonFormat 以与日期过滤器和日期字段相同的方式进行注释,如下所示:

Class Filter {
...
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="dd/MM/yyyy HH:mm", timezone="America/Sao_Paulo")
private Date startDate;
}

Class YourObject {
...

@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="dd/MM/yyyy HH:mm", timezone="America/Sao_Paulo")
private Date DateAdded;
}

模式和时区应根据您所在的地区进行调整。

【讨论】:

    【解决方案2】:

    重要的是要知道,当使用 BETWEEN 时,“setDate”会截断作为参数传递的 HQL 日期值并忽略小时、分钟、秒。需要注意这一点非常重要,特别是如果您有一个 HQL 查询检查不同日期的日期,因为使用“setDate”会将日期间隔解释为指定日期的午夜之间。

    解决方案是使用“setParameter”而不是“setDate”,这会导致 HQL 日期值被解释为日期和时间。

    以下是我网站中的一些示例,供有兴趣的人使用 http://www.coding-dude.com/wp/java/hql-date-datetime-quick-tip/

    【讨论】:

    • 如果您链接到您的网站,您需要添加免责声明。
    【解决方案3】:
    SimpleDateFormat formatter = new SimpleDateFormat("MM-dd-yyyy");
        Calendar c = Calendar.getInstance();
        c.setTime(new Date()); // Now use today date.
        c.add(Calendar.DATE, 90);
        Date fromDate = null, toDate = null;
        String fromDateStr = formatter.format(new Date());
        String toDateStr = formatter.format(c.getTime());
        try {
            fromDate = formatter.parse(fromDateStr);
            toDate = formatter.parse(toDateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        query.setParameter("stDate", fromDate);
        query.setParameter("edDate", toDate);
    

    【讨论】:

      【解决方案4】:

      我有类似的问题。当我们使用结束日期(1 月 29 日星期三)时,系统会查找 1 月 29 日星期三 00:00:00,这就像选择 1 月 28 日一样。为了避免这种情况,我们可以在结束日期上增加一天。这也解释了为什么我们对开始日期没有问题。

      令人惊讶的是,当我们使用休眠条件时,这个问题并不存在。

      【讨论】:

        【解决方案5】:
        SimpleDateFormat sf=new SimpleDateFormat("dd-MM-YYYY");
        String fromDate=null;
        String toDate=null;
        fromDate=sf.format(startDate);
        toDate=sf.format(endDate);
        sessionfactory.getCurrentSession().createQuery("from Customer where dateAdded BETWEEN '"+startDate+"' AND '"+endDate+"'");
        

        【讨论】:

        • 你应该解释你的答案,而不仅仅是发布代码。
        【解决方案6】:

        这是一篇旧帖子,但我认为它可能对某人有所帮助。设置 .setTimeStamp 应该可以解决问题。

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String frmDate = format.parse(startDate);
        String enDate = format.parse(endDate); 
        sessionfactory.getCurrentSession()
        .createQuery("FROM Customer AS c WHERE c.dateAdded BETWEEN :stDate AND :edDate ")
        .setTimestamp("stDate", frmDate)
        .setTimestamp("edDate", enDate)
        .list();
        

        【讨论】:

          【解决方案7】:
          SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
          String frmDate = format.parse(startDate);
          String enDate = format.parse(endDate);
          sessionfactory.getCurrentSession()
          .createQuery("FROM Customer AS c WHERE c.dateAdded BETWEEN :stDate AND :edDate ")
          .setParameter("stDate", frmDate)
          .setParameter("edDate", enDate)
          .list();
          

          希望这会有所帮助!

          【讨论】:

          • 当您将格式化的日期返回到 Date 对象时,这将不起作用,所有格式都消失了
          • 这也行不通 :( 因为 setParameter 将检查传递的变量类型。因此它会引发 String 和 Date 之间转换失败的异常。即使您尝试在 setParameter 中转换它也赢了不工作
          • 在写问题时使用旧样式
          • 是的,这肯定是目前最合适的解决方案,但这并不是最好的,因为它使代码容易受到 SQL 注入的影响,设置参数被认为是避免安全漏洞并确保代码是类型安全的
          【解决方案8】:

          试试这样的:

          SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
          Date fromDate = df.parse(startDate);
          Date toDate = df.parse(endDate);
          Criteria criteria = sessionfactory.getCurrentSession().createCriteria(Customer.class)
             .add(Restrictions.between("dateAdded", fromDate , toDate ));
          List<Customer> listCustomer = criteria.list();
          

          希望这会有所帮助..!!

          【讨论】:

          • 当您将格式化的日期返回到 Date 对象时,这将不起作用,所有格式都消失了
          猜你喜欢
          • 1970-01-01
          • 2017-05-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-10-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多