如何在 JPA 查询中将日期时间转换为日期

Posted

技术标签:

【中文标题】如何在 JPA 查询中将日期时间转换为日期【英文标题】:How to convert Datetime to Date in JPA query 【发布时间】:2019-01-23 10:55:06 【问题描述】:

我正在使用 Spring data JPA 编写复杂的查询,比如说统计查询。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class StatisticsPair 
  private LocalDateTime time;
  private BigDecimal balance;


@Data
@Entity
@Table(name="t_order")
public class Order 
  private LocalDateTime createdTime;
  private BigDecimal amount;
  private OrderStatus status;

在存储库中查询:

@Query("select new xxx.StatisticsPair(createdTime, sum(amount)) from Order where createdTime >= ?1 and createdTime <= ?2 and status = xxx.OrderStatus.COMPLETED group by createdTime")
List<StatisticsPair> statAmountByDay(LocalDateTime from, LocalDateTime to);

方法statAmountByDay 给了我这样的结果:

[
  "time": "2006-01-02 15:04:05", "balance": 100.00
  "time": "2006-01-02 16:04:05", "balance": 200.00
  "time": "2006-01-03 15:04:05", "balance": 200.00
]

但我要按天统计,只需要日期,时间没用,预期结果:

[
  "time": "2006-01-02", "balance": 300.00
  "time": "2006-01-03", "balance": 200.00
]

所以我想知道如何将createdTime(datetime type) 转换为Date 类型,就像mysql 中的函数DATE(createdTime),但我不想使用本机查询,因为我的代码在不同的ENV 上运行,使用不同的数据库。

【问题讨论】:

【参考方案1】:

我知道这不是最好的方法,但在我找到更好的解决方案之前,您可以将返回的时间作为字符串处理(使用 SUBSTRING)

xxx.StatisticsPair(substring(cast(createdTime as nvarchar(19)), 1, 10), sum(amount))

或尝试:

xxx.StatisticsPair(cast(createdTime as date), sum(amount))

【讨论】:

受你的启发,它现在可以工作了,但我仍在寻找一种优雅的方式,我认为可能是 SpEL 可以提供帮助。 ` @Query("select new xxx.StatisticsPair(createdTime, sum(amount)) from Order where createdTime >= ?1 and createdTime time 字段包含时间信息,但我可以查询后处理。 对风格感到抱歉,*** 在评论中的降价很糟糕。 有两件事要说。首先是您可以尝试转换为日期,正如我在编辑中提到的那样。二是如果你认为我的回答是对的,那你能接受吗? 转换不起作用,这是一个非法的ArgumentException,但substringgroup by 子句中工作,这是导入的东西,给了我正确的结果,我仍在寻找更好的方法。跨度> 【参考方案2】:

您有两种可能的解决方案:

    将对象 StatisticsPair 中的 LocalDateTime 更改为具有 LocalDate 而不是 LocalDateTime,希望 Spring JPA 仅采用日期组件:

....

@Data
@AllArgsConstructor
@NoArgsConstructor
public class StatisticsPair 
    private LocalDate date;
    private BigDecimal balance;

    第二种解决方案是在 StatisticsPair 列表上使用 java 和 java 流进行操作:

....

List<StatisticsPair> list = ... ;
List<StatisticsPairWithDate> listWithDate;
listWithDate = list
            .stream()
            .map(sp-> 
                    new StatisticsPairWithDate(
                            sp.getTime().toLocalDate(), 
                            sp.getBalance()))
            .collect(Collectors.toList()); 

....

@Data
@AllArgsConstructor
@NoArgsConstructor
public class StatisticsPairWithDate 
  private LocalDate date;
  private BigDecimal balance;

==============================================

@Query("select new xxx.StatisticsPair(createdTime, sum(amount)) from Order where createdTime >= ?1 and createdTime <= ?2 and status = xxx.OrderStatus.COMPLETED group by createdTime")
List<StatisticsPair> statAmountByDay(LocalDate from, LocalDate to);

【讨论】:

我想你误解了我,这不是关于结果,而是关于我传递给数据库的参数。对于结果 2006-01-02 15:04:052006-01-02 都可以映射到 LocalDateTime 只是你可以使用 LocalDate 作为参数。 JPA 引擎应该负责其余的工作。 查看底部最后的更新,只需更改参数,JPA会处理。

以上是关于如何在 JPA 查询中将日期时间转换为日期的主要内容,如果未能解决你的问题,请参考以下文章