简体   繁体   English

需要帮助创建JPA条件查询

[英]Need help creating JPA criteria query

I'm building my first Java EE web application using Glassfish and JSF. 我正在使用Glassfish和JSF构建我的第一个Java EE Web应用程序。 I'm fairly new to the criteria query and I have a query I need to perform but the javaee6 tutorial seems a little thin on examples. 我对条件查询相当新,我有一个我需要执行的查询,但javaee6教程在示例上似乎有点薄。 Anyway, I'm having a hard time creating the query. 无论如何,我很难创建查询。

Goal: I want to pull the company with the most documents stored. 目标:我希望用最多的文档来存储公司。 Companies have a OneToMany relationship with Documents. 公司与文档具有OneToMany关系。 Documents has a ManyToOne relationship with several tables, the "usertype" column distinguishes them. Documents与多个表具有ManyToOne关系,“usertype”列区分它们。

MySQL query: MySQL查询:

SELECT USERID, COUNT(USERID) AS CNT 
FROM DOCUMENTS 
WHERE USERTYPE="COMPANY" 
GROUP BY USERID 
ORDER BY CNT DESC

Thanks 谢谢

--update-- Based on user feedback, here is what I have so far: --update--根据用户反馈,这是我到目前为止:

        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Documents> cqry = cb.createQuery(Documents.class);
        //Intersting Stuff
        Root<Documents> root = cqry.from(Documents.class);
        Expression userid = root.get("userID");
        Expression usertype = root.get("userType");
        Expression count = cb.count(userid);
        cqry.multiselect(userid, count);
        Predicate userType = cb.equal(usertype, "COMPANY");
        cqry.where(userType);
        cqry.groupBy(userid);
        cqry.orderBy(cb.desc(count));
        //more boilerplate
        Query qry = em.createQuery(cqry);
        List<Documents> results = qry.getResultList();

The error I get is: 我得到的错误是:

Exception Description: Partial object queries are not allowed to maintain the cache or be edited.  You must use dontMaintainCache().

Typical error, means nothing to me! 典型的错误,对我来说没什么意义!

Your query doesn't return a complete entity object as you're only selecting two fields of the given table (this is why you're getting an error that says yadayadapartialyadayada ). 您的查询不会返回完整的实体对象,因为您只选择给定表的两个字段(这就是您收到yadayadapartialyadayada错误的原因 )。

Your solution is almost right, here's what you need to change to make it work—making it partial . 您的解决方案几乎是正确的,这是您需要更改以使其工作的部分

Instead of a plain CriteriaQuery<...> you have to create a tuple CriteriaQuery<..> by calling CriteriaBuilder.createTupleQuery() . 而不是简单的CriteriaQuery<...>你必须通过调用CriteriaBuilder.createTupleQuery()来创建一个元组 CriteriaQuery<..> (Basically, you can call CriteriaBuilder.createQuery(...) and pass Tuple.class to it as an argument. Tuple is a sort of wildcard entity class.) (基本上,你可以调用CriteriaBuilder.createQuery(...)并通过Tuple.class把它作为一个参数。 Tuple是一种通配符实体类的。)

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Tuple> cq= cb.createTupleQuery();

Root<Documents> root = cq.from(Documents.class);
Expression<Integer> userId = root.get("USERID");
Expression<String> userType = root.get("USERTYPE");
Expression<Long> count = cb.count(userId);

cq.multiselect(userId.alias("USERID"), count.alias("CNT"));
cq.where(cb.equal(userType, "COMPANY");
cq.groupBy(userId);
cq.orderBy(cb.desc(count));

TypedQuery<Tuple> tq = em.createQuery(cq);
for (Tuple t : tq.getResultsList()) {
  System.out.println(t.get("USERID"));
  System.out.println(t.get("CNT"));
}

(Accessing fields of a Tuple gave me an error if I didn't use aliases for them (in multiselect(...) ). This is why I've used aliases, but this can be tackled more cleanly by using JPA 2's Metamodel API , which is described in the specification quite thoroughly. ) (如果我没有为它们使用别名,访问Tuple字段会给我一个错误(在multiselect(...) )。这就是我使用别名的原因,但是使用JPA 2的Metamodel可以更清晰地解决这个问题。 API ,在规范中非常详尽地描述。

The documentation for CriteriaQuery.multiselect(...) describes the behaviour of queries using Tuple objects more deeply. CriteriaQuery.multiselect(...)的文档描述了更深入地使用Tuple对象的查询行为。

If you are using Hibernate, this should work: 如果你正在使用Hibernate,这应该工作:

ProjectionList pl = Projections.projectionList()
.add(Projections.groupProperty("userid"))
.add(Projections.property("userid"))
.add(Projections.count("userid"));

Criteria criteria = session.createCriteria(Document.class)
.add(Restrictions.eq("usertype",usertype))
.setProjection(pl)
.addOrder(Order.desc("cnt"));

Hope it helps! 希望能帮助到你!

Take a look into this easy tutorial. 看看这个简单的教程。 It uses JPA2 and Criteria 它使用JPA2和Criteria

http://www.jumpingbean.co.za/blogs/jpa2-criteria-api http://www.jumpingbean.co.za/blogs/jpa2-criteria-api

Regards! 问候!

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

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