在Java中使用CriteriaBuilder进行日期比较

时间:2018-12-21 09:37:09

标签: java hibernate criteria

我当前有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);

第一种方法尝试了

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>>

我尝试的第二种方法是:

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>)

我尝试的第三种方法是:

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 :(得分:0)

选项1.纯Java

您需要自己实现FunctionExpression。下面是我的自定义“包含”功能的类(在Ms Sql Server中进行全文搜索)。您需要用“%s和%s之间的datepart(wk,%s)”替换“ contains(%s,%s)”,并使用2个属性“ Expression value”代替我的一个。在数据库文档中查找“ 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方法,但是不允许在SQL datepart函数中提供wk常量。如果您的数据库具有datapart(wk,{date})的内置模拟,例如week({date}),则可以编写

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

它将转换为SQL

week(yourTable.dateField) between ? and ?

如果数据库没有内置函数,则应创建用户定义的函数。

答案 1 :(得分:0)

解决方案是基础知识

 criteriaQuery.select(root).where(
 criteriaBuilder.greaterThanOrEqualTo(root.<Date>get("date"), MondayOfTheWeek()),
 criteriaBuilder.lessThanOrEqualTo(root.<Date>get("date"), FridayOfTheWeek()));