如何使用CriteriaBuilder构造形式为SELECT a FROM e.attributes a ....
的子查询,其中e
是外部查询中引用的某些实体?
我有一些涉及自由格式键-值结构的实体类(这存在其自身的问题,但这就是我所拥有的)。我需要找到存在某些键值对的实体。我可以将其写为以下形式的JPQL查询:
SELECT e FROM Entity e
WHERE e.type = 'foo'
AND EXISTS (SELECT a FROM e.attributes a
WHERE a.key = 'bar'
AND a.value = 'baz')
对于固定的查询字符串,我可以使用EntityManager.createQuery()创建查询:
EntityManager em = /* ... */;
TypedQuery<Entity> tq = em.createQuery(queryString, Entity.class);
在实践中,查询中有多个 EXISTS ,因此我需要使用CriteriaBuilder构造查询。到目前为止,我得到的最接近的结果是子查询SELECT a from Attributes a WHERE ...
,但是不限于e.attributes
,
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Entity> query = cb.createQuery(Entity.class);
Root<Entity> root = query.from(Entity.class);
Subquery<Attribute> subquery = query.subquery(Attribute.class);
Root<Attribute> subroot = subquery.from(Attribute.class); // too broad
subquery.select(subroot)
.where(cb.and(//
cb.equal(subroot.get("key"), cb.literal("bar")),
cb.equal(subroot.get("value"), cb.literal("baz"))));
query.select(root)
.where(cb.and(//
cb.equal(root.get("type"), cb.literal("foo")), //
cb.exists(subquery)));
子查询上有许多correlate()
方法,我想知道是否需要在外部查询中将具有其属性的Entity联接起来,然后以某种方式关联(),但是我不确定从EE7 javadocs确切的相关性是做什么的(但是correlate()确实返回一个From,这意味着我可以从中进行SELECT,这很有希望)。
答案 0 :(得分:0)
我最终在JPA 2.0 spec中找到了答案。在第276页上有一个相关查询的示例:
示例4:特例
为了表达一些涉及单向关系的相关子查询,将子查询的域与包含查询的域相关联可能很有用。这是通过使用Subquery接口的相关方法来完成的。
例如:
// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.1.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { google() jcenter() flatDir { dirs 'libs' } } } task clean(type: Delete) { delete rootProject.buildDir }
此查询对应于以下Java Persistence查询语言查询:
CriteriaQuery<Customer> q = cb.createQuery(Customer.class); Root<Customer> customer = q.from(Customer.class); Subquery<Long> sq = q.subquery(Long.class); Root<Customer> customerSub = sq.correlate(customer); Join<Customer,Order> order = customerSub.join(Customer_.orders); q.where(cb.gt(sq.select(cb.count(order)), 10)) .select(customer);
令我困扰了一会儿,让我想到也许我的JPQL可能不合法,是因为FROM子句的语法(同一规范中的第173页)的给出方式为:
SELECT c FROM Customer c WHERE (SELECT COUNT(o) FROM c.orders o) > 10
我不清楚from_clause ::= FROM identification_variable_declaration ...
identification_variable_declaration ::= range_variable_declaration ...
range_variable_declaration ::= entity_name [AS] identification_variable
之类的东西如何可以成为“ entity_name”。事实证明,子查询FROM子句的语法中实际上还有其他整个产品,其中包括集合支持:
e.attributes