Как лучше всего запросить объект JPA для экземпляров на основе текущей даты и времени?

У меня есть тип объекта с двумя датами: startDate и endDate:

import org.joda.time.DateTime;

@Entity
public class Thing {
    @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    private DateTime startDate;

    @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    private DateTime endtDate;
}

У меня есть репозиторий Spring Data-JPA (расширяет CrudRepository) для этого типа сущности, и там мне нужен способ запроса всех Thing, которые являются «активными», где «активный» определяется как

startDate ‹= now‹ = endDate

Я пробовал выполнить такой запрос JPQL, но он не дал ожидаемых результатов в некоторых наших тестах:

@Query("select t from Thing t where t.startDate <= CURRENT_TIMESTAMP and t.endDate >= CURRENT_TIMESTAMP")
public Iterable<Thing> findAllActive();

Я также попробовал запрос с соглашением о названии метода, который дает ожидаемые результаты, но это неудобно:

public Iterable<Thing> findByStartDateBeforeAndEndDateAfter(DateTime minStartDate, DateTime maxEndDate);

Я могу обернуть это своим @Service лайком

public Iterable<Thing> getActiveThings() {
    DateTime now = DateTime.now();
    return repository.findByStartDateBeforeAndEndDateAfter(now, now);
}

Так что интерфейс сервиса чистый, но интерфейс репо уродлив и неудобен (на мой взгляд).

Есть ли лучший способ создать этот метод запроса репозитория с использованием JPA: лучший запрос на основе имени метода или явный запрос JPQL? Я бы предпочел не создавать вручную объект Query в коде (сейчас у меня даже нет конкретного класса для репозитория, только интерфейс), но если это лучший способ, я подумаю об этом.


person E-Riz    schedule 18.02.2014    source источник
comment
каково значение CURRENT_TIMESTAMP?   -  person TheKojuEffect    schedule 18.02.2014
comment
CURRENT_TIMESTAMP - это встроенная функция в JPQL, которая возвращает текущую дату и время в базе данных. См. stackoverflow.com/a/1659088/639520   -  person E-Riz    schedule 18.02.2014
comment
Я написал запрос JPQL, который включает сравнение дат, которое отлично работает, но я использовал тип Date по умолчанию, в отличие от указанного вами типа. Попробуйте использовать java.util.Date, чтобы узнать, не вызывает ли @Type проблемы.   -  person TheKojuEffect    schedule 18.02.2014
comment
Сначала проверьте, во что преобразован JPQL, и убедитесь, что хранилище может обрабатывать сравнения с использованием выбранного вами типа даты.   -  person Chris    schedule 18.02.2014
comment
@TheKojuEffect, мы не меняем сущности для использования java.util.Date, библиотека Joda Time намного более функциональна, и мы уже основали на ней логику в приложении. Я знаю, что он поддерживает сравнения, потому что версия с именем метода работает (это просто уродливо).   -  person E-Riz    schedule 18.02.2014
comment
@Chris, Joda DateTime хранится как отметка времени в БД (по крайней мере, для MySQL и H2 это так). Как я уже сказал, сгенерированный Spring запрос на основе имени метода работает должным образом, поэтому я знаю, что этот тип работает для сравнений.   -  person E-Riz    schedule 18.02.2014


Ответы (2)


У вас может быть просто следующее:

@Query("select t from Thing t where t.startDate <= :time and t.endDate >= :time")
public Iterable<Thing> findActiveThings(@Param("time") DateTime time);

Который имеет то преимущество, что использует только 1 параметр, но также позволяет вам позже получать такие запросы, как: «Дайте мне список активных действий на 24 января 2011 года».

person Guillaume Polet    schedule 29.01.2015

Вы можете написать обходной путь, примерно так:

@Query("SELECT t FROM Thing t WHERE t.startDate <= :maxStartDate AND :minEndDate <= t.endDate")
public Iterable<Thing> findAllActive();

И создайте DateTime maxStartDate и DateTime minEndDate, которые, например, 2015-01-01 00:00:00 и 2015-01-01 23:59:59

DateTime maxStartDate= new DateTime().withTime(23, 59, 59, 0);
DateTime minEndDate = new DateTime().withTimeAtStartOfDay();
person Tomasz Godziński    schedule 29.01.2015