将日期参数传递给本机查询

时间:2017-07-03 09:57:09

标签: spring postgresql hibernate jpa

用户可以根据事件值执行操作。当此值等于“每日”时,我想检索过去24小时内尚未完成的所有日常操作。

正在运行的SQL查询:

SELECT distinct a.* FROM action as a LEFT OUTER JOIN history as h
ON a.id = h.action_id
AND h.user_id= <user> WHERE a.occurrence = 'DAILY' AND (h.id is NULL OR h.entry_date < TIMESTAMP 'yesterday')

等效的原生查询:

@Query(value = 
        "SELECT distinct a.* FROM action a "
        + "LEFT OUTER JOIN history h "
        + "ON a.id = h.action_id "
        + "AND h.user_id = :userId "
        + "WHERE a.occurrence='DAILY' AND (h.id IS NULL OR h.entry_date < :yesterday) ", nativeQuery = true)
public List<Action> findAllAvailableActions(@Param("userId") Long userId, @Param("yesterday") ZonedDateTime yesterday);

如何在我的服务中调用它:

ZonedDateTime today = ZonedDateTime.now(ZoneOffset.UTC);
ZonedDateTime yesterday = today.minus(1,ChronoUnit.DAYS);
Long userId = userDTO.getId();
List<Action> result = actionRepositoryCustom.findAllAvailableActions(userId, yesterday);

但是,我在测试中得到了错误的结果(已经完成的操作被返回)。我担心这与日期参数有关。 entry_date属性在我的实体中声明为ZoneDateTime。我做错了什么?

  

休眠:5.2.4

1 个答案:

答案 0 :(得分:2)

您无法将ZonedDateTime传递给本机SQL查询。您需要将其转换为日历:

@Query(value = 
    "SELECT distinct a.* FROM action a "
    + "LEFT OUTER JOIN history h "
    + "ON a.id = h.action_id "
    + "AND h.user_id = :userId "
    + "WHERE a.occurrence='DAILY' AND (h.id IS NULL OR h.entry_date < :yesterday)", nativeQuery = true)
public List<Action> findAllAvailableActions(@Param("userId") Long userId, @Param("yesterday") Calendar yesterday);

你可以这样转换你的ZonedDateTime:

public Calendar convertToDatabaseColumn(ZonedDateTime entityAttribute) {
    if (entityAttribute == null) {
        return null;
    }

    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(entityAttribute.toInstant().toEpochMilli());
    calendar.setTimeZone(TimeZone.getTimeZone(entityAttribute.getZone()));
    return calendar;
}

此处描述了此方法:link