【问题标题】:JPA @NamedQuery with bitwise AND (&) as criteriaJPA @NamedQuery 以按位与 (&) 作为条件
【发布时间】:2014-02-10 09:02:25
【问题描述】:

有谁知道如何使用按位 AND (&) 作为 JPA NamedQuery 的条件而不必使用 @NamedNativeQuery?

我将状态位存储在一个字段中。

我正在为视图实体使用以下定义:

@NamedQueries({
    @NamedQuery(name="ViewProductsList.findAll", query="SELECT v FROM ViewProductsList v"),
    @NamedQuery(name="ViewProductsList.findFeatured", query="SELECT v FROM ViewProductsList v WHERE v.statusId & 16"),
    @NamedQuery(name="ViewProductsList.findBySubcategory", query="SELECT v ViewProductsList v WHERE v.subcatId IN (:subcatIds)"),
})

第一个工作正常,但第二个不喜欢表达,我得到以下内容:

18:02:13,528 DEBUG [DataNucleus.Query] - JPQL Single-String with "SELECT v FROM ViewProductsList v WHERE v.statusId & 16"
18:02:13,553 DEBUG [DataNucleus.Query] - JPQL Query : Compiling "SELECT v FROM ViewProductsList v WHERE v.statusId & 16"
>>ERROR: 'Portion of expression could not be parsed: & 16'

在生产中使用 dev MySQL 数据库和 Google Cloud SQL,因此它必须在两个版本上都可以工作...

有什么想法吗?

更新问题:

当使用如下定义的@NamedNativeQuery 时:

@NamedNativeQuery(name = "ViewProductsList.findFeatured", query = "SELECT * FROM view_products_list v")

并调用如下:

Query query=em.createNativeQuery("ViewProductsList.findFeatured", ViewProductsList.class);
List<ViewProductsList> list = query.getResultList();

我收到以下错误:

java.lang.IllegalStateException: You cannot invoke getResultList/getSingleResult when the Query is an UPDATE/DELETE
    at org.datanucleus.api.jpa.JPAQuery.getResultList(JPAQuery.java:161)
    at cultivartehidroponia.ProductsServlet.doGet(ProductsServlet.java:81) ...

我尝试了许多不同的 createNativeQuery 示例,但均未成功。有人知道使用 datanucleus 的本地查询示例吗?

同样,使用带有 createNamedQuery 的普通 @NamedQuery 可以正常工作!

提前致谢!!!

【问题讨论】:

    标签: mysql jpa datanucleus bitwise-and


    【解决方案1】:

    Bitwise AND 不是 JPQL 的一部分。但是……

    可以使用2条规则:

    1. 除以 2^х 会将位右移 x(例如 1011010/1000=1011)
    2. 如果右位为 1,则 z mod 2 = 1(例如 1011 mod 2 = 1)

    试试

    SELECT v FROM ViewProductsList v WHERE MOD(v.statusId/16 , 2) = 1
    

    【讨论】:

    • 尽管您的回答是正确的,而且这是一种很好的方法。我认为在 sql 上按位做会比 mod 和除法快得多
    • 可能是我没有得到您的解决方案,但看起来它不起作用。此查询应返回相同的结果,但不同:select day from (select 62 as day /*2 4 8 16 32*/ union all select 30 /*2 4 8 16*/ union all select 32 /*32*/ ) as t where day &amp; 32select day from (select 62 as day/*2 4 8 16 32*/ union all select 30/*2 4 8 16*/ union all select 32/* 32*/ ) as t where MOD(day/32, 2) = 1
    【解决方案2】:

    “按位与”不是 JPQL 的一部分。原生查询是一种可移植的方式。

    【讨论】:

    • 谢谢!我想了很多,但我试图避免它,因为它返回了各种错误。我已经更新了关于使用本机查询的原始问题。你有什么指示吗?问候!
    • 执行命名本机查询的问题绝对为零(JPA TCK 也没有)。如果您有问题,建议您生成一个有效的测试用例来演示这样的事情,并在使用的软件网站上报告它,并提及正在使用的版本(如果不是当前版本,请说明为什么不这样做)
    【解决方案3】:

    答案很晚,但仍然是一个……您可以在 SQL 端声明一个执行按位操作(移位和屏蔽)的函数。例如(PostgreSQL):

    CREATE OR REPLACE FUNCTION extractBits(bitmap bigint, bitOffset integer, bitMask bigint) RETURNS bigint
        LANGUAGE plpgsql IMMUTABLE
        AS $$
    BEGIN
        return (bitmap >> bitOffset) & bitMask;
    END;$$ RETURNS NULL ON NULL INPUT;
    

    然后,如果/当使用 JPA 标准构建器时,您可以使用以下内容:

    Expression<Long> bitmap = ...; // Path or expression to raw bitmap
    
    Expression<Long> extracted = 
        builder.function("extractBits", Long.class, bitmap, shiftCount, bitMask);
    
    Predicate predicate = builder.equal(extracted, desiredValue);
    

    如果您希望在 JPQL 中使用,它会有所不同,但这里有关于如何操作的答案。例如:

    Calling an oracle function from JPA

    那个有 EclipseLink 链接的答案: http://www.eclipse.org/eclipselink/documentation/2.5/jpa/extensions/j_func.htm

    使用休眠: https://thorben-janssen.com/database-functions/

    【讨论】:

      猜你喜欢
      • 2016-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-18
      • 1970-01-01
      相关资源
      最近更新 更多