繁体   English   中英

Java JPA 规范如何与位操作一起使用

[英]How Java JPA Specification works with bit operations

我正在尝试在规范中运行一些位操作,但文档很少。

例如,我有一个带有 bit(32) 字段roles的表tb_user 我正在尝试搜索具有特定翻转位(位 = 1)的记录。 假设我搜索 b'1011' 并且结果应该返回所有翻转了 bit0 或 bit1 或 bit3 的记录。 如果我搜索 b'0011' 并且结果应该返回具有 bit0、bit1 翻转的记录。

我怎样才能在 JPA 规范中做到这一点?

    public static Specification<TbUser> role(Integer roles) {
    return ObjectUtils.isEmpty(roles) ?
            (root, query, builder) -> builder.conjunction() :
            (root, query, builder) -> {
            // How do I run the bit operations?
           
    }
}

我看不到按位 AND 是 SQL 的一部分; JPA/JPQL 被编写为与数据库无关,因此不会在其中内置特定于数据库的支持(Transact-SQL?)。

JPA 3 规范部分“4.6.17.3”有一个“FUNCTION”运算符,可用于将“&”应用于您的参数。 Criteria api 有一个“函数”方法可以操作相同,但您必须提供预期的返回类型才能在大于表达式中使用它。 就像是

  Expression<Integer> bitwiseAnd = builder.function("&", Integer.class, root.get("role"), 4);
  builder.greaterThan(bitwiseAnd, 0);

在我的尽头

builder.function("&", Integer.class, root.get("role"), 4);

会触发错误

java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '&(tb_user0_.role, 524290)>0 or &(tb_user0_.role, 524290)<0)' at line 1

所以我不能在规范中直接使用“&”。

另一种有效的方法如下:

// customize a MySQL5Dialect with new registered function
public class ExtendedMySQL5Dialect extends MySQL5Dialect {
    public ExtendedMySQL5Dialect() {
        super();
        // added bitwise operators
        registerFunction("bit_and", new SQLFunctionTemplate(IntegerType.INSTANCE, "(?1 & ?2)"));
        registerFunction("bit_or", new SQLFunctionTemplate(IntegerType.INSTANCE, "(?1 | ?2)"));
        registerFunction("bit_xor", new SQLFunctionTemplate(IntegerType.INSTANCE, "(?1 ^ ?2)"));
    }
}

// change your yaml or property file
spring:
  application:
  name: user-service
  jpa:
    hibernate:
      ddl-auto: update
    database-platform: com.package.path.ExtendedMySQL5Dialect

//implementation of specification
public static Specification<TbUser> role(Integer roles) {
    return ObjectUtils.isEmpty(roles) ?
        (root, query, builder) -> builder.conjunction() :
        (root, query, builder) -> {
            Expression<Integer> bitwiseAnd = builder.function("bit_and", Integer.class, root.get("role"), 4); 
            return builder.greaterThan(bitwiseAnd, 0);
       
        }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM