Есть ли чистое решение для достижения инклюзивного начала и эксклюзивного завершения в QueryDSL/Oracle SQL?

Я пытаюсь создать запрос для временного интервала с помощью QueryDSL (включая начало, эксклюзивную дату окончания).

В документация QueryDSL. Я обнаружил, что public BooleanExpression between(Expression<T> from, Expression<T> to); является эксклюзивным с обеих сторон,

Получить первое ‹ это ‹ второе выражение

однако он преобразуется в Oracle SQL BETWEEN, который включает обе стороны
(эквивалентно first <= this <= second).

такой QueryDSL:

[...]
person.name.like(n)
  .and(person.birthdate.between(from, to))
[...]

переводится в Oracle SQL следующим образом:

SELECT *
FROM PERSON
WHERE NAME LIKE n
  AND BIRTHDATE BETWEEN from AND to;

Кто-нибудь знает причины/логику этого?
Это просто "гнилая" документация?

Ясно, что между мной не сработает никоим образом.

Должен ли я использовать более неуклюжий

person.name.like(n)
  .and(person.birthdate.goe(from)
  .and(person.birthdate.lt(to))

или есть чистое решение, которое делает то, что я хочу?


person MrMeszaros    schedule 03.08.2015    source источник
comment
Если бы это был простой SQL, я бы использовал between "from" and "to" - 1? (при условии, что to_ является значением DATE   -  person a_horse_with_no_name    schedule 03.08.2015
comment
Это работает, только если все даты усечены @a_horse; фактический запрос OP будет between "from" and "to" - interval '1' second   -  person Ben    schedule 03.08.2015


Ответы (2)


Документация уже была исправлена ​​некоторое время назад http://www.querydsl.com/static/querydsl/2.2.0/apidocs/com/mysema/query/types/expr/ComparableExpression.html#between(T,%20T)

Версия 2.2.0 была выпущена 18 июля 2011 г. Я настоятельно рекомендую вам использовать более новую версию Querydsl начиная с 4.* или 3.*.

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

public static <T> Predicate range(ComparableExpression<T> expr, T from, T to) {
    return expr.goe(expr).and(expr.lt(to));
}
person Timo Westkämper    schedule 03.08.2015

Это выглядит просто некачественной документацией, однако я не думаю, что это имеет большое значение. Если бы документация делала то, что предлагается, то это было бы неуместно для вас; то, что происходит в настоящее время, немного лучше.

В диалекте Oracle SQL нет ни одного выражения, которое представляло бы операцию first <= this < second. Таким образом, вам все равно придется сделать что-то вроде этого:

person.name.like(n)
  .and(person.birthdate.between(from, to)
  .and(person.birthdate.lt(to))

который будет представлен в SQL как:

select *
  from person
 where name like n
   and birthdate between from and to
   and birthdate < to

В этот момент так же легко четко заявить о своих намерениях и сделать то, что вы намереваетесь:

person.name.like(n)
  .and(person.birthdate.goe(from)
  .and(person.birthdate.lt(to))

P.S. Я немного удивлен, что column.like(String) становится column like string в SQL; это эквивалентно column = string. Я ожидал, что .like() станет column like string || '%', что будет искать в начале столбца строку, которую вы запрашиваете.

person Ben    schedule 03.08.2015