【问题标题】:Spring Data JPA (JPQL) problem: Using TIMESTAMPDIFF function in JPA querySpring Data JPA (JPQL) 问题:在 JPA 查询中使用 TIMESTAMPDIFF 函数
【发布时间】:2019-05-03 19:57:17
【问题描述】:

我有以下 MySQL 查询:

select p.name, sum(timestampdiff(MINUTE, r.start_time, r.end_time)) 
from ride r inner join person p on r.driver_id=p.id 
group by p.id

我想在 JPA 查询中写这个。下面的代码抛出 NullPointerException,它不起作用:

@RestResource
public interface SomeRepository extends CrudRepository<Ride, Long> {

@Query("SELECT new com.sample.dto.MyDTO(d.name, SUM(FUNCTION('TIMESTAMPDIFF', 'MINUTE', r.startTime, r.endTime))) " +
      "FROM Ride r JOIN r.driver d WHERE r.startTime BETWEEN ?1 AND ?2 " +
      "GROUP BY d.id" )
  List<MyDTO> findSomething(@Param("startTime") LocalDateTime startTime,
                                   @Param("endTime") LocalDateTime endTime);

}    

如果我使用 DATEDIFF 函数,它可以工作。

FUNCTION('DATEDIFF', r.startTime, r.endTime)

但我需要以分钟为单位的确切差异。 TIMESTAMPDIFF 满足我的需求。 在找不到如何使用 JPA 执行此操作后,我返回到本机查询,但这并不好。有其他选择吗?

我用的是最新的spring-data-jpa(2.1.3),hibernate-core:5.3.7

public class Ride {
  @Column(name = "start_time")
  private LocalDateTime startTime;

  @Column(name = "end_time")
  private LocalDateTime endTime;

 }

目标是找出 startTime 和 endTime 之间的总差异(以分钟为单位)。有没有办法用标准(便携式)JPA 做到这一点?

【问题讨论】:

  • 为什么你认为原生查询不好?恕我直言,这非常适合您尝试实现的目标。原生查询在很多情况下都可以。
  • 是的,这里的 JPA 就像一个不必要的层,给我带来的麻烦多于帮助。我将使用本机查询而不是与 JPQL 搏斗。
  • @Query(value="...", nativeQuery = true) Object[][] findSomething(..) 这个对象数组并映射它并不好。 (结果不是实体,只是聚合函数结果。)
  • @Bhdr 如果你真的想使用 JPA,你可以试试我的解决方案。
  • 谢谢库纳尔。我试过了,没用,有时间我再试试。

标签: spring spring-boot spring-data-jpa spring-data spring-data-rest


【解决方案1】:

org.hibernate.dialect.MySQLDialect 中没有 registerFunction('TIMESTAMPDIFF')。

但是 registerFunction('DATEDIFF') 存在。

所以你不能在 jpa 中使用 TIMESTAMPDIFF。

您可以添加自定义功能或使用自定义方言。

但我建议改用 unix_timestamp()。

(function('unix_timestamp', startTime)-function('unix_timestamp', endTime))/60

【讨论】:

    【解决方案2】:

    实际上,JPQL 中没有 TIMESTAMPDIFF。

    参考:timestampdiff equivalent in JPQL (without using criteria)

    所以,你可以做的是,你可以使用TIME_TO_SEC(TIMEDIFF(r.startTime, r.endTime)) / 60,而不是使用FUNCTION('TIMESTAMPDIFF', 'MINUTE', r.startTime, r.endTime)

    【讨论】:

    • 这行得通,但是如果你想在 DB 级别限制结果,JPA 似乎不支持它。对于类似 "ORDER BY blah LIMIT ?3" 的内容,我们需要再次进行原生查询。有什么想法吗?
    • @Bhdr LIMIT 子句有一个替代方案。探索Pageable 界面。请参阅stackoverflow.com/questions/9314078/…。由于PageRequest的构造函数已被弃用,请参考stackoverflow.com/questions/44848653/…
    猜你喜欢
    • 2020-08-08
    • 2017-11-28
    • 2017-11-30
    • 1970-01-01
    • 2015-12-23
    • 1970-01-01
    • 2015-03-18
    • 2021-09-07
    • 2012-09-13
    相关资源
    最近更新 更多