传递日期参数给本地查询

问题描述:

用户可以根据事件值执行操作。当这个值等于'每日'时,我想检索所有在过去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

如何ENTRY_DATE在数据库中宣布什么type是数据库中的entry_date?还有数据库中的entry_date是否保存在UTC时区中? –

+0

entry_date在我的数据库中被描述为没有时区的** timestamp。我确实在Java中使用以下语法来保存它:\t \t'historyDTO.setEntryDate(ZonedDateTime.now(ZoneOffset.UTC));' –

你不能传递到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

+0

我对你写的帖子留下了深刻的印象(我想因为我不读俄语: p)当我面对这个问题的时候,因为我无法解决它,所以我使用了一个存储过程,但实际上你的解决方案看起来更干净。我同意这个逻辑,我已经尝试过使用另一个函数,结果看起来是正确的。谢谢@dimirsen –

+0

不客气!我的英语足以回答相当复杂的问题:)我最近碰到了同样的问题,并决定分享我的解决方案。 – dimirsen