Проблема Spring Data JPA (JPQL): использование функции TIMESTAMPDIFF в запросе JPA

У меня есть следующий запрос 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?

как вы думаете, почему нативный запрос не подходит? ИМХО, это идеально подходит для того, чего вы пытаетесь достичь. Собственные запросы подходят во многих ситуациях.

Simon Martinelli 02.12.2018 11:36

Да, здесь JPA был как ненужный слой, который доставил мне больше проблем, чем помог. Я буду использовать собственный запрос вместо борьбы с JPQL.

Bhdr 02.12.2018 14:27

@Query (value = "...", nativeQuery = true) Object [] [] findSomething (..) этот массив объектов и отображение нехорошо. (Результатом является не сущность, а результат агрегированной функции.)

Bhdr 02.12.2018 14:30

@Bhdr Вы можете попробовать мое решение, если действительно хотите использовать JPA.

Kunal Puri 03.12.2018 01:42

Спасибо, Кунал. Я пробовал, не получилось, но попробую еще раз, когда у меня будет время.

Bhdr 03.12.2018 08:32

@Bhdr Подскажите, пожалуйста, полученную вами ошибку? Я выполнил простой запрос, используя тот же подход с моей стороны, и он работал.

Kunal Puri 03.12.2018 15:25

@KunalPuri да, это работает, но мне также нужно ограничить результат на уровне БД. Кажется, JPA тоже не поддерживает это. "ЗАКАЗАТЬ БЛАГОДАРНОСТЬ ЛИМИТУ? 3"

Bhdr 05.12.2018 15:30
0
7
2 463
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Собственно, в JPQL нет TIMESTAMPDIFF.

Ссылка: эквивалент timestampdiff в JPQL (без использования критериев)

Итак, вы можете использовать TIME_TO_SEC(TIMEDIFF(r.startTime, r.endTime)) / 60 вместо FUNCTION('TIMESTAMPDIFF', 'MINUTE', r.startTime, r.endTime).

это работает, но если вы хотите ограничить результаты на уровне БД, похоже, JPA не поддерживает. Для чего-то вроде «ORDER BY blah LIMIT? 3» нам снова нужен собственный запрос. Любые идеи?

Bhdr 05.12.2018 15:33

@Bhdr Есть альтернатива LIMIT. Изучите интерфейс Pageable. Обратитесь к stackoverflow.com/questions/9314078/…. Поскольку конструкторы PageRequest устарели, обратитесь к stackoverflow.com/questions/44848653/…

Kunal Puri 06.12.2018 02:58

В org.hibernate.dialect.MySQLDialect нет registerFunction ('TIMESTAMPDIFF').

Но registerFunction ('DATEDIFF') существует.

Таким образом, вы не можете использовать TIMESTAMPDIFF в jpa.

Вы можете добавить настраиваемую функцию или использовать собственный диалект.

Но я предлагаю вместо этого использовать unix_timestamp ().

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

Другие вопросы по теме