【问题标题】:getting all date values in a date range in hibernate在休眠中获取日期范围内的所有日期值
【发布时间】:2012-01-26 10:27:51
【问题描述】:

我需要知道如何获取 Hibernate 查询结果集中某个日期范围内的所有日期。

应该类似于下面的SQL伪代码

从 ???? 中选择“所有日期”之间的日期 TO_DATE('date-val','format') 和 TO_DATE('date-val','format')。

它可能需要一些不同的逻辑,但如果我给出一个范围,比如 2011 年 2 月 5 日到 2011 年 3 月 2 日 它应该返回结果集中该范围内的所有日期... 即

结果集 = 2011 年 2 月 5 日、2011 年 2 月 6 日、..... 2011 年 2 月 28 日、2011 年 3 月 1 日、 2011 年 3 月 2 日


更新: 以下查询在 Oracle 中给出了所需的结果集

select 
    d.dateInRange as dateval,
    eventdesc,
    nvl(td.dist_ucnt, 0) as dist_ucnt
from (
    select 
        to_date('03-NOV-2011','dd-mon-yyyy') + rownum - 1 as dateInRange
    from all_objects
    where rownum <= to_date('31-DEC-2011','dd-mon-yyyy') - to_date('03-NOV-2011','dd-mon-yyyy') + 1
) d
left join (
    select 
        currentdate,
        count(distinct(grauser_id)) as dist_ucnt,
        eventdesc 
    from
        txn_summ_dec

    group by currentdate, eventdesc 
) td on td.currentdate = d.dateInRange order by d.dateInRange asc

Resultset:
Date                    eventdesc       dist_cnt
2011-11-03 00:00:00     null                0
and so on..
2011-11-30 00:00:00     null                0
2011-12-01 00:00:00     Save Object         182
....
2011-12-31 00:00:00     null                0

【问题讨论】:

  • 你真的需要用 Hibernate 做这个吗?听起来像是与持久性无关的 Java 逻辑的工作。标准 API CalendarJoda Time 都可以很好地满足要求。
  • 我也可以使用 Java,只是为了明确这样做的目的,最后我想在这个结果集上做一个左连接,在这个范围内我的用户数量不同,按日期分组,这样我对结果集中的所有日期都有计数(即使某个日期没有计数)

标签: java hibernate


【解决方案1】:

这个逻辑应该负责生成范围:

public static List<Date> dayRange(Date begin, Date end) {
    if (end.before(begin)) {
        throw new IllegalArgumentException("Invalid range");
    }

    final List<Date> range = new ArrayList<>();
    final Calendar c1 = extractDate(begin);
    final Calendar c2 = extractDate(end);

    while (c1.before(c2)) {
        range.add(c1.getTime()); // begin inclusive
        c1.add(Calendar.DATE, 1);
    }
    range.add(c2.getTime()); // end inclusive

    return range;
}

private static Calendar extractDate(Date date) {
    final Calendar c = Calendar.getInstance();

    c.setTime(date);
    c.set(Calendar.HOUR, 0);
    c.set(Calendar.MINUTE, 0);
    c.set(Calendar.SECOND, 0);
    c.set(Calendar.MILLISECOND, 0);

    return c;
}

不像 Joda Time 那样漂亮和简洁,但可以让你继续前进。

如果您只需要为没有结果的日期显示带有零的查询结果,请运行按日期分组的原始查询(没有左连接),然后填写缺失的日期。假设您的查询返回Map&lt;String, Long&gt;

final DateFormat df = new SimpleDateFormat("d-MMM-yyyy", Locale.US);

final Date begin = df.parse("5-Feb-2011");
final Date end = df.parse("2-March-2011");

final List<Date> range = dayRange(begin, end);
final Map<String, Long> result = // code to execute your query

for (Date date: range) {
    String key = df.format(date);
    if(!result.containsKey(key)) {
        result.put(key, 0l);
    }
}

我希望这会有所帮助。

【讨论】:

  • 这是一个很好的框架,但它缺少最重要的部分——“执行查询的代码”。现在我已经设法计算出基于 Oracle 的查询可以直接在结果集中获得所需的结果 - 不需要任何代码来修改结果集,现在只需将其转换为 HQL/标准 api!请检查帖子上的更新
  • @pri_dev,我的观点是您不需要查询的前半部分。只需执行后半部分 - 在左连接之后(如果您在将其映射到 HQL 时遇到问题,请阅读 here),将结果提取到 Map(如果您在将结果提取到 Map 时遇到问题,请阅读 here)并使用我添加缺失日期的代码。这样做可以清除吗?
  • 好的:)。只是为了清除它,您需要查询的后半部分加上 between startDate and endDate 之类的过滤日期。应将结果提取到诸如TreeMap&lt;Date, Object[]&gt;TreeMap&lt;Date, MyCustomObjectForDescAndCount&gt; 之类的数据结构中。然后可以使用我的代码将缺少的 date -&gt; [null desc, 0 count] 对放入地图中。
猜你喜欢
  • 1970-01-01
  • 2012-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多