我想使用 Criteria API 进行日期算术运算。例如,在 Postgres 中我可以编写这样的查询:
select * from appointment a where a.date + interval '2 days' > '2022-10-21';
如何使用 Criteria 实现此语法?我是否必须编写自己的 Expression 类,或者是否有任何内置的东西可供我使用?
我尝试了这样的方法,但没有成功:
private class DateArithmetricExpression<T extends Date> extends ExpressionImpl<T> {
private final int value;
private final ChronoUnit unit;
private final BinaryArithmeticOperation.Operation operator;
private final Expression<T> date;
public DateArithmetricExpression(CriteriaBuilderImpl cb, Class<T> clazz, Expression<T> date, BinaryArithmeticOperation.Operation operator, int value, ChronoUnit unit) {
super(cb, clazz);
this.value = value;
this.unit = unit;
this.operator = operator;
this.date = date;
}
@Override
public void registerParameters(ParameterRegistry registry) {
}
@Override
public String render(RenderingContext renderingContext) {
String op = switch (operator) {
case ADD -> "+";
case SUBTRACT -> "-";
default -> throw new UnsupportedOperationException();
};
String renderedDateExpr = ((Renderable) this.date).render(renderingContext);
return "%s %s interval '%d %s'".formatted(renderedDateExpr, op, value, unit.toString());
}
}
你可以这样做:
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Appointment> criteriaQuery = criteriaBuilder.createQuery(Appointment.class);
Root<Appointmet> itemRoot = criteriaQuery.from(Appointmet.class);
criteriaQuery.where(
criteriaBuilder.greaterThan(
criteriaBuilder.function("sql", Date.class, "? + INTERVAL '2 days'", itemRoot.get("date")),
criteriaBuilder.literal(new Date(2022, Calendar.NOVEMBER, 21)))
);
TypedQuery<Apppointment> query = entityManager.createQuery(criteriaQuery);
return query.getResultList();