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 некрасив, но я понятия не имею, как от этого избавиться:(

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