如何在QueryDSL中使用按位运算符?

时间:2017-03-01 15:30:03

标签: java spring spring-data-jpa querydsl

您好,

在我的项目中,我有一个字段标志(int),我需要使用几个条件查询数据库,其中一个是标志字段,在我的实体中我有一个字段标志,它是一个枚举,同一个字段可以通过将它们相互添加来保存多个值,然后使用&提取我需要的结果。运营商。 例如:在数据库中flag = 4 + 128 = 132 我需要通过应用AND运算符来检查标志是否保持值128,因此应用查询: SELECT * from rate where(flag& 128)> 0 所以我需要的是使用Querydsl和spring data jpa发送bitwise_AND。

我尝试使用QuerydslBinderCustomizer,但无法找到任何将任何按位运算符应用于整数的方法。 我还尝试创建一个自定义的BooleanExpression将其返回到bindings.bind,它手动应用了bitwise运算符,但它也没有工作。

这是我需要的一个例子:

public interface RateRepository extends CrudRepository<Rate,RatePK>, QueryDslPredicateExecutor<Rate>, QuerydslBinderCustomizer<QRate> {

@Override
default void customize(QuerydslBindings bindings, QRate qRate) {
    bindings.bind(qRate.rateId).first(
            (path, value) -> {
                return (path & value > 0) //Something like this, or a function like:
                //return (bitwise_AND(path, value) > 0);
            });
}

}

我也尝试过使用com.querydsl.core.types.dsl.Expressions和com.querydsl.core.types.Predicate,如下所示:

bindings.bind(qRate.rateFlag).first(
            (path, value) -> {
                Expression<Integer> intPath = Expressions.asNumber(path);
                Expression<Integer> rateFlag = Expressions.asNumber(value);
                Expression<Integer> zeroValue = Expressions.asNumber(0);
                Expression<Integer> integerExpression = Expressions.numberOperation(Integer.class, Ops.AND, intPath, rateFlag);
                Predicate predicate  = Expressions.predicate(Ops.GT, integerExpression, zeroValue);
                return predicate;
            });

但是我得到了一个无效的运算符AND错误。

怎么可以这样做?

谢谢。

1 个答案:

答案 0 :(得分:1)

首先你需要扩展hibernate方言以支持位操作,如下所示

public class MySQLDialect extends org.hibernate.dialect.MySQLDialect {

    public MySQLDialect() {
        super();
        registerFunction("bitand", new SQLFunctionTemplate(IntegerType.INSTANCE, "(?1 & ?2)"));
    }
}

然后你可以从querydsl或spring repository

引用这个函数
bindings.bind(qRate.rateFlag).first(
            (path, value) -> {
                Expression<Integer> zeroValue = Expressions.asNumber(0);
                NumberTemplate<Integer> numberTemplate = Expressions.numberTemplate(Integer.class, "function('bitand', {0}, {1})", path, value);
                return numberTemplate.gt(0);
            });