Criteria hibernate inner join projection group by - java

I`m having some trouble translating this SQL to Hibernate Criteria. I have seached it for some time, but couldnt get any ideas as how to do it.
SELECT * FROM tableA a
INNER JOIN (
SELECT tableA_nr AS cod, max(tableA_status) as sit
FROM tableA
GROUP BY (tableA_nr)
) status_nr_list
ON a.tableA_nr = status_nr_list.cod and a.tableA_status = status_nr_list.sit
ORDER BY tableA_nr;
Here´s what I´ve accomplished so far.
criteria.setProjection(
Projections.projectionList()
.add(Projections.groupProperty("tableA_nr"))
.add(Projections.max("tableA_status.id")));
Thanks in advance!

Not sure if this works but the hint is you can use Detached Criteria for subquery.
Sub query
DetachedCriteria status_nr_list = DetachedCriteria.forClass(tableA_nr.class, "tableA_nr");
status_nr_list.setProjection(Projections.max("tableA_status"));
status_nr_list.setProjection(Projections.property("tableA_nr"));
Main query
session.createCriteria(tableA_nr.class)
.add( Subqueries.propertyIn("tableA_nr", status_nr_list) )
.add( Subqueries.propertyIn("tableA_status", status_nr_list) );

Related

Criteria Builder select from select

Can anybody help me to create JPA Criteria Builder query in order to achieve this ?:
select id from (
select distinct r.id
r.date
r.name
from report r
inner join unit u
on u.report_id = r.id
order by
r.date desc,
r.name asc)
where rownum <= 10
I just can create inner query:
CriteriaQuery<Object[]> innerQuery = cb.createQuery(Object[].class);
Root<ReportEntity> root = innerQuery.from(ReportEntity.class);
List<Ojbect[]> resultLsit = em.createQuery(
innerQuery.multiselect(root.get(ReportEntity_.id),
root.get(ReportEntity_.date),
root.get(ReportEntity_.name)
.distinct(true)
.orderBy(cb.desc(root.get(ReportEntity_.date)),
cb.asc(root.get(ReportEntity.name))
).setMaxResults(10).getResultList();
Thx in advance :)
I've decided to get List of Object[] and then retrieve id from array
List idList = resultList.stream().map(array -> (Long)array[0]).collect(Collectors.toList());
This is code smell, but unfortunatelly I haven't found better solution.
Note I use this approach to cope Hibernate issue :
"Warning “firstResult/maxResults specified with collection fetch; applying in memory!”? - this warning pops up due to using fetch and setMaxResults in hql or criteria query.
That's why first of all I get all id, and then I find all entities according this id. (select * from ReportEntity r where r.id in :idList) - smth like this.

HQL to Criteria

I am trying to create a Criteria from HQL.
Simplified HQL:
SELECT
event.pkid,
add.name
FROM Event event
LEFT JOIN event.addresses adds
JOIN adds.address add
WHERE adds is null
or adds.addressType = 'EVENT'
And I use following Criteria to produce an equivalent query.
criteria.createAlias("addresses", "adds",
CriteriaSpecification.LEFT_JOIN)
.createAlias("adds.address", "add",
CriteriaSpecification.LEFT_JOIN)
.setProjection(
Projections
.projectionList()
.add(Projections.property("pkid"))
.add(Projections
.property("add.name")))
.add(Restrictions.or(Restrictions.isNull("addresses"),
Restrictions.eq(
"adds.addressType.addressType",
"EVENT")));
But it produces following query,
select
this_.pkid as y0_,
add2_.name as y1_
from event this_
left outer join event_address_map adds1_ on this_.pkid=adds1_.event_pkid
where (this_.pkid is null or adds1_.address_type=?)
Second join is not added. What am I doing wrong?
Thanks in advance.

Join tables hibernate + group by

I need to do this query with Java + Hibernate.
SELECT
table2.id,
COUNT(table2.id) AS count
FROM
table1
JOIN table2
ON table1.fk_tb2 = table2.id --many2one
GROUP BY
table2.id
I would use DetachedCriteria class.....how can i do this ?
Try using projections like this:
Criteria table1Crit = session.createCriteria("table1");
Criteria table2Crit = table1Crit.createCriteria("table2", Criteria.INNER_JOIN);
table2Crit.setProjection( Property.forName("id").count() );
use your query with createNativeQuery method

Hibernate Criteria - Exclude groupProperty from select

I would like to use a hibernate criteria object as a subquery on a second criteria, like this:
DetachedCriteria latestStatusSubquery = DetachedCriteria.forClass(BatchStatus.class);
latestStatusSubquery.setProjection(Projections.projectionList()
.add( Projections.max("created"), "latestStatusDate")
.add( Projections.groupProperty("batch.id"))
);
DetachedCriteria batchCriteria = DetachedCriteria.forClass(BatchStatus.class).createAlias("batch", "batch");
batch.add( Property.forName( "created" ).eq( latestStatusSubquery ) );
The problem is that adding a groupProperty automatically add that property to the select clause on the subselect query and I can't find any way to stop this from happening.
The result, of course a DB error because the subquery returns too many values.
Does anyone know a way around this?
Try like below sample,
DetachedCriteria subquery = DetachedCriteria.forClass(CustomerCommentsVO.class, "latestComment");
subquery.setProjection(Projections.max("latestComment.commentId"));
subquery.add(Expression.eqProperty("latestComment.prospectiveCustomer.prospectiveCustomerId", "comment.prospectiveCustomer.prospectiveCustomerId"));
objCriteria = objSession.createCriteria(CustomerCommentsVO.class,"comment");
objCriteria.add(Subqueries.propertyEq("comment.commentId", subquery));
List lstComments = objCriteria.list();

Hibernate detached queries as a part of the criteria query

java experts can you please help me write detached queries as a part of the criteria query for the following SQL statement.
select A.*
FROM AETABLE A
where not exists
(
select entryid
FROM AETABLE B
where B.classpk = A.classpk
and B.userid = A.userid
and B.modifiedDate > A.modifiedDate
)
and userid = 10146
You need to write a correlated subquery. Assuming property / class names match column / table names above:
DetachedCriteria subquery = DetachedCriteria.forClass(AETable.class, "b")
.add(Property.forName("b.classpk").eqProperty("a.classpk"))
.add(Property.forName("b.userid").eqProperty("a.userid"))
.add(Property.forName("b.modifiedDate").gtProperty("a.modifiedDate"));
Criteria criteria = session.createCriteria(AETable.class, "a")
.add(Property.forName("userid").eq(new Integer(10146)))
.add(Subqueries.notExists(subquery);
Just one addition to the above query. If the entryid is not the primary key, then you'll need to add projection.
DetachedCriteria subquery = DetachedCriteria.forClass(AETable.class, "b")
.add(Property.forName("b.classpk").eqProperty("a.classpk"))
.add(Property.forName("b.userid").eqProperty("a.userid"))
.add(Property.forName("b.modifiedDate").gtProperty("a.modifiedDate"))
.add(setProjection(Projections.property("entryId")); // Additional projection property
Criteria criteria = session.createCriteria(AETable.class, "a")
.add(Property.forName("userid").eq(new Integer(10146)))
.add(Subqueries.notExists(subquery);

Categories