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

How to use bitwise operators in QueryDSL?

嗨,

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

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

这是我需要的示例:

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

但是我遇到了无效的运算符和错误。

这是怎么做到的?

谢谢。

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

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

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

然后您可以从 querydsl 或 spring 存储库

引用此函数
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);
            });