Сравнение дат с использованием CriteriaBuilder в Java - PullRequest
0 голосов
/ 21 декабря 2018

У меня ток date(date) и friday(fridayOfTheWeek) и Monday(mondayOfTheWeek).Я хочу проверить, находится ли дата между понедельником и пятницей, включая.

Я пытался использовать метод предикатов и get, но не смог его реализовать

    CriteriaBuilder builder = session.getCriteriaBuilder();
    CriteriaQuery<Star> criteriaQuery = builder.createQuery(Teacher.class);
    Root<Teacher> root = criteriaQuery.from(Teacher.class);
    Join<Teacher, B> join = root.join("department").join("team");
    criteriaQuery.where(builder.equal(join.get("department"), "subject"));
   //criteriaQuery.where(builder.between(root.get("date")), MondayOfTheWeek(), FridayOfTheWeek());
    criteriaQuery.select(root);
    Query<Teacher> query = session.createQuery(criteriaQuery);

1-й метод попробовал это

criteriaQuery.where(builder.between(builder.function("week", Integer.class, root.get("date")), MondayOfTheWeek(), FridayOfTheWeek()));

и ошибка, которую я получаю на builder.between это

Bound mismatch: The generic method between(Expression<? extends Y>, Y, Y) of type CriteriaBuilder is not applicable for the arguments (Expression<Integer>, Date, Date). The inferred type Object&Comparable<?>&Serializable is not a valid substitute for the bounded parameter <Y extends Comparable<? super Y>>

2-й метод, который я попробовал:

criteriaQuery.where(builder.between(root.get("date")), MondayOfTheWeek(), FridayOfTheWeek());

Он дает ошибку, между которой

The method between(Expression<? extends Y>, Expression<? extends Y>, Expression<? extends Y>) in the type CriteriaBuilder is not applicable for the arguments (Path<Object>)

3-й метод, который я попробовал:

ParameterExpression<java.util.Date> parameter = builder.parameter(java.util.Date.class);
Predicate startPredicate = builder.greaterThanOrEqualTo(root.get(MondayOfTheWeek()), parameter);
Predicate endPredicate = builder.greaterThanOrEqualTo(root.get(FridayOfTheWeek()), parameter);

Ошибка, которую я получаю:

The method get(SingularAttribute<? super Teacher,Y>) in the type Path<Teacher> is not applicable for the arguments (Date)

Ответы [ 2 ]

0 голосов
/ 23 декабря 2018

Решение было в основах:

 criteriaQuery.select(root).where(
 criteriaBuilder.greaterThanOrEqualTo(root.<Date>get("date"), MondayOfTheWeek()),
 criteriaBuilder.lessThanOrEqualTo(root.<Date>get("date"), FridayOfTheWeek()));
0 голосов
/ 21 декабря 2018

Вариант 1. Чистая Java

Вам необходимо создать собственную реализацию FunctionExpression .Ниже мой класс для пользовательской функции «содержит» (Полнотекстовый поиск в Ms Sql Server).Вам нужно заменить «contains (% s,% s)» на что-то вроде «datepart (wk,% s) между% s и% s» и использовать 2 свойства «Значение выражения» вместо моего.Ищите описание «datepart» в документации к вашей базе данных.

import org.hibernate.query.criteria.internal.CriteriaBuilderImpl;
import org.hibernate.query.criteria.internal.ParameterContainer;
import org.hibernate.query.criteria.internal.ParameterRegistry;
import org.hibernate.query.criteria.internal.Renderable;
import org.hibernate.query.criteria.internal.compile.RenderingContext;
import org.hibernate.query.criteria.internal.expression.LiteralExpression;
import org.hibernate.query.criteria.internal.expression.function.BasicFunctionExpression;

import javax.persistence.criteria.Expression;
import java.io.Serializable;

/**
 * Models a SQL <tt>CONTAINS</tt> expression.
 *
 * @author Steve Ebersole
 */
public class ContainsFunction extends BasicFunctionExpression<Boolean> implements Serializable {
    private final Expression<String> field;
    private final Expression<String> value;

    public ContainsFunction(CriteriaBuilderImpl criteriaBuilder, Expression<String> field, Expression<String> value) {
        super(criteriaBuilder, Boolean.class, "contains");
        this.field = field;
        this.value = value;
    }

    public ContainsFunction(
            CriteriaBuilderImpl criteriaBuilder,
            Expression<String> field,
            String value) {
        this(criteriaBuilder, field, new LiteralExpression<>(criteriaBuilder, value));
    }

    public Expression<String> getField() {
        return field;
    }

    public Expression<String> getValue() {
        return value;
    }

    public void registerParameters(ParameterRegistry registry) {
        ParameterContainer.Helper.possibleParameter(getField(), registry);
        ParameterContainer.Helper.possibleParameter(getValue(), registry);
    }


    @Override
    public String render(RenderingContext renderingContext) {
        return String.format("contains(%s,%s)=true" 
                , ((Renderable) getField()).render(renderingContext)
                , ((Renderable) getValue()).render(renderingContext));
    }
}

Использование этого пользовательского выражения

query.where(new ContainsFunction((CriteriaBuilderImpl) builder, field, value))

Опция 2. Java + DB

Вы можете использовать CirtiaBuilder # function метод, но он не позволяет вводить константу wk в функцию datepart SQL.Если в вашей базе данных есть встроенный аналог для datapart (wk, {date}), например, недели ({date}), тогда вы можете написать

query.where(builder.between(builder.function("week", Integer.class, root.get("dateField")), first, last));

, и он будет переведен в SQL

week(yourTable.dateField) between ? and ?

Если ваша база данных не имеет встроенной функции, вам следует создать пользовательскую функцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...