QueryDSL, Spring Data: выберите дату и время между константой и значением базы данных с помощью Predicate
Привет я хотел бы создать предикат для пружинных данных QueryDSLRepository, который будет генерировать следующий запрос (или эквивалентный):
SELECT * FROM USER user JOIN PASSWORD_POLICY policy
ON
user.password_policy_oid = policy.password_policy_oid
WHERE
user.password_expiration_date BETWEEN CURRENT TIMESTAMP - (SELECT EXPIRATION_WARN_PERIOD_IN_DAYS FROM PASSWORD_POLICY subQueryPolicy WHERE subQueryPolicy.password_policy_oid = policy.password_policy_oid) DAYS AND CURRENT TIMESTAMP
Значение этого запроса будет следующим: "Получите от меня всех пользователей, у которых истекает срок действия пароля"
и под истечением срока я имею в виду - срок действия пароля истекает между сейчас и (сейчас - EXPIRATION_WARN_PERIOD_IN_DAYS из таблицы PASSWORD_POLICY)
Является ли это возможным?
1 ответ
Вероятно, этого нельзя сделать, используя только предикат Spring Data. AFAIK jpql не поддерживает такие манипуляции с датой и временем (добавление дней и т. Д.). Итак, что вы можете сделать, если вы все еще хотите использовать Querydsl, - это использовать нативный JPASQLQuery. К сожалению, присоединение сопоставленных объектов не так просто, еще один недостаток заключается в том, что возможности манипуляции с датой и временем не так хороши в Querydsl. Но я смог справиться с твоей проблемой.
Предположения:
Пользователь содержит поле @ManyToOne PassworPolicy, которое отображается столбцом PASSWORD_POLICY_OID.
База данных DB2
import static model.QPasswordPolicy.passwordPolicy;
import static model.QUser.user;
import static com.mysema.query.sql.SQLExpressions.datediff;
import static com.mysema.query.types.expr.DateTimeExpression.currentTimestamp;
...
NumberPath<Integer> userPasswordPolicyOidPath = new NumberPath<>(Integer.class, QUser.user, "PASSWORD_POLICY_OID");
QPasswordPolicy subQueryPolicy = new QPasswordPolicy("subQueryPolicy");
List<Integer> userIds =
new JPASQLQuery(entityManager, new DB2Templates())
.from(user)
.join(passwordPolicy).on(passwordPolicy.passwordPolicyOid.eq(userPasswordPolicyOidPath))
.where(datediff(DatePart.day, currentTimestamp(DateTime.class), user.passwordExpirationDate)
.lt(new JPASubQuery().from(subQueryPolicy)
.where(passwordPolicy.passwordPolicyOid.eq(subQueryPolicy.passwordPolicyOid))
.unique(passwordPolicy.expirationPeriodInDays)))
.list(user.userOid);
возможно, для удовлетворения логики требуется еще одно условие expirationDate PS
userPasswordPolicyOidPath некрасив, но я понятия не имею, как от этого избавиться:(