У меня есть следующий запрос 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.
Спасибо, Кунал. Я пробовал, не получилось, но попробую еще раз, когда у меня будет время.
@Bhdr Подскажите, пожалуйста, полученную вами ошибку? Я выполнил простой запрос, используя тот же подход с моей стороны, и он работал.
@KunalPuri да, это работает, но мне также нужно ограничить результат на уровне БД. Кажется, JPA тоже не поддерживает это. "ЗАКАЗАТЬ БЛАГОДАРНОСТЬ ЛИМИТУ? 3"
Собственно, в 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 Есть альтернатива LIMIT. Изучите интерфейс Pageable. Обратитесь к stackoverflow.com/questions/9314078/…. Поскольку конструкторы PageRequest устарели, обратитесь к stackoverflow.com/questions/44848653/…
В org.hibernate.dialect.MySQLDialect нет registerFunction ('TIMESTAMPDIFF').
Но registerFunction ('DATEDIFF') существует.
Таким образом, вы не можете использовать TIMESTAMPDIFF в jpa.
Вы можете добавить настраиваемую функцию или использовать собственный диалект.
Но я предлагаю вместо этого использовать unix_timestamp ().
(function('unix_timestamp', startTime)-function('unix_timestamp', endTime))/60
как вы думаете, почему нативный запрос не подходит? ИМХО, это идеально подходит для того, чего вы пытаетесь достичь. Собственные запросы подходят во многих ситуациях.