Hi i'm struggling to write the following query with criteria api:
"SELECT c.id,curr.name FROM Cargo c, Currency curr"
The problem is that both Cargo and Currency are aliased as c by criteria so the resulting jpql becomes "SELECT c.id,c.name FROM Cargo c, Currency c".
I don't know if it is because both entities start with C.
Is there a way to chage the table alias?
CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Tuple> query= criteriaBuilder.createTupleQuery();
Root<Cargo> cargo= query.from(Cargo.class);
Root<Currency> currency= query.from(Currency.class);
Any help is very much appreciated.
Your code is missing the part where you specify what you want selected. "SELECT c.id,curr.name FROM Cargo c, Currency curr"
would likely translate to something like:
CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
CriteriaQuery<Tuple> query= criteriaBuilder.createTupleQuery();
Root<Cargo> cargo= query.from(Cargo.class);
Root<Currency> currency= query.from(Currency.class);
query.multiselect(cargo.get("id"), currency.get("name"));
Query query = em.createQuery(cq);
List<Tuple> results = query.getResultList();
There is an example here using only one table:
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/Criteria#Tuple_Queries
After lots of debugging, i found out that the actual jpql that is executed is different from the one that is displayed in my ide(eclipse).
The aliases were ok.I think i was a bit deceived by the ide.
Thanks all for your attention.
Related
SELECT recipe.name,SUM(salesdetails.quantity::integer),recipe.price As Quantity
FROM (salesinfo JOIN salesdetails ON salesinfo.sessionid=salesdetails.salesinfo_sessionid)
JOIN recipe ON salesdetails.recipe_id=recipe.id group by salesdetails.recipe_id,recipe.name,recipe.price
ORDER BY SUM(salesdetails.quantity::integer) DESC;
Can anyone give me the hql query for this?
If you are not acquainted with the HQL and want to use the same query ,then you can do it using the native query feature of the Hibernate like this :
#QUERY(value="SELECT recipe.name, SUM(salesdetails.quantity::
INTEGER),recipe.price AS Quantity
FROM (salesinfo
JOIN salesdetails ON salesinfo.sessionid=salesdetails.salesinfo_sessionid)
JOIN recipe ON salesdetails.recipe_id=recipe.id
GROUP BY salesdetails.recipe_id,recipe.name,recipe.price
ORDER BY SUM(salesdetails.quantity:: INTEGER) DESC", nativeQuery = TRUE)
But I would recommend that you first try to convert the same in into HQL query and then if any issue then you should ask it here instead of directly asking for the converted query. Meanwhile this can help.
I would like to get first row from database using JPA Criteria. I use JPA, Hibernate 4.2.7.
In SQL, statement looks like:
SELECT * FROM houses WHERE rownum = 1;
My Java code to achive that looks like:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<House> query = builder.createQuery(House.class);
Root<House> root = query.from(House.class);
query.select(root).where(builder.equal(root.get("rownum"), 1));
TypedQuery<House> tQuery = entityManager.createQuery(query);
House house = tQuery.getSingleResult();
But 'rownum' pseudocolumn cannot be resolved, I get exception:
java.lang.IllegalArgumentException: Unable to resolve attribute [rownum] against path
at org.hibernate.ejb.criteria.path.AbstractPathImpl.unknownAttribute(AbstractPathImpl.java:120)
at org.hibernate.ejb.criteria.path.AbstractPathImpl.locateAttribute(AbstractPathImpl.java:229)
at org.hibernate.ejb.criteria.path.AbstractPathImpl.get(AbstractPathImpl.java:200)
Is is possible, and if so, how to get 'rownum' pseudocolumn with Criteria API? Thanks for any suggestions.
You can accomplish this using setFirstResult and setMaxResults.
session.createCriteria(Foo.class)
.setFirstResult(0)
.setMaxResults(1);
you can set rownum or limits in property of query;
Query q =entityManager.createQuery("select * from employee_table");
q.setFirstResult(0);
q.setMaxResults(30);
I have to write that HQL query:
FROM Sending adp WHERE adp.id = (SELECT MAX (adpw.id) FROM Sending adpw WHERE adpw.place = adp.place)
I have to use Criteria API and I can't manage it. Query returns last sendings from all places in database and it works very well but now I have to transform it to Criteria. The only thing I managed is to show just one place with following code:
Criteria criteria = getSession().createCriteria(
Sending.class);
criteria.setFetchMode("place", FetchMode.JOIN);
DetachedCriteria maxId = DetachedCriteria.forClass(Sending.class).setProjection(Projections.max("id"));
criteria.add(Property.forName("id").eq(maxId));
Could you help me? Thanks in advance!!
Sorry for answering my own question, but I found the solution.
I forgot that Subqueries can be correlated with themselves. I realized my query with following code:
Criteria criteria = getSession().createCriteria(Sending.class);
DetachedCriteria dc = DetachedCriteria.forClass(Sending.class, "adpw");
dc.add(Restrictions.eqProperty("adpw.place", "adp.place"));
dc.setProjection(Projections.max("id"));
criteria.add(Property.forName("id").eq(dc));
criteria.setMaxResults(count).setFirstResult(start);
return criteria.list();
Everything works now very well.
I'm building my first Java EE web application using Glassfish and JSF. 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. 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.
Documents has a ManyToOne relationship with several tables, the "usertype" column distinguishes them.
MySQL query:
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:
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).
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(). (Basically, you can call CriteriaBuilder.createQuery(...) and pass Tuple.class to it as an argument. Tuple is a sort of wildcard entity class.)
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. )
The documentation for CriteriaQuery.multiselect(...) describes the behaviour of queries using Tuple objects more deeply.
If you are using Hibernate, this should work:
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
http://www.jumpingbean.co.za/blogs/jpa2-criteria-api
Regards!
You need to add a constructor to Documents with only userid and count because you will need it on:
cqry.multiselect(userid, count);
I have a native SQL query I would like to express with a JPA2 criteria query.
This query already works, but I haven't been able to get it using just JPA2.
I think mostly because I lack experience on this.
I paste the SQL here, maybe you experts can help me to figure it out:
SELECT * FROM
OWNING_POINTS o1
JOIN
(SELECT conversationId, count(*) as nOfMsg
FROM OWNING_POINTS
GROUP BY conversationId) as o2
ON o1.conversationId = o2.conversationId
LEFT JOIN
(SELECT id, created as newerUnreadMessage
FROM OWNING_POINTS
WHERE `read`=0) as o3
ON o1.id = o3.id " +
WHERE o1.owner_user_id=?
ORDER BY newerUnreadMessage DESC, nOfMsg DESC
Thank you very much.