如何在 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 查询中将日期时间转换为日期的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Presto 中将时间戳转换为日期?

如何在 SQL Server 中将字符串转换为日期时间?

无法在 MySQL 查询中将字符串转换为日期时间

如何在标准 SQL 中将 Epoch 时间戳转换为日期

如何在 PHP 中将标准 AS400 CYMD 日期格式转换为 MDY?

如何在python中将字符串日期转换为日期时间格式? [复制]