Convert a SQL query to hql - sql

I need to convert this query to hql to use it my code :
SELECT DISTINCT
certificate_id , last_scan
FROM
bcs_certificate_instance
ORDER BY
last_scan
LIMIT 5 ;
Who can help please?

select distinct bci.certificate_id , bci.last_scan
from bcs_certificate_instance bci
order by last_scan asc;
And for limit you have to use setMaxResults() funtion on query object before executing it.
A code snippet for this would look like:
Query query = em.createQuery(“select distinct bci.certificate_id , bci.last_scan
from bcs_certificate_instance bci
order by last_scan asc;”);
query.setMaxResults(10);
List resultData = query.getResultList();
Thats it. So that is how you limit the number of records returned by a query in HQL.
Example with #Query annotation:
public interface PersonDao extends EntityDao<Person, Long> {
#Query("select p from Person p where p.age between ?1 and ?2")
QueryResult<Person> findAllByAge(int minAge, int maxAge);
}
Once you have obtained a QueryResult, you can apply further options and restrictions to the query:
List<Person> result = personDao.findAllByAge(18, 65)
.sortAsc(Person_.lastName)
.sortDesc(Person_.age).
.firstResult(10)
.maxResults(10)
.getResultList();
}

Related

Jpa Specification ORA-01791: not a SELECTed expression

I have a problem with Jpa Specification.
My specification looks like this:
public static Specification<PersonView> getByFilter(PersonViewFilter filter) {
return (root, query, criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();
SetJoin<PersonView, PersonDetailsView> personDetailsJoin =
root.join(PersonView_.personDetails);
Path<String> namePath = personDetailsJoin.get(PersonDetailsView_.name);
Path<String> surnamePath = personDetailsJoin.get(PersonDetailsView_.surname);
predicates.add(namePredicate(personDetailsJoin, criteriaBuilder, filter.getName()));
predicates.add(surnamePredicate(personDetailsJoin, criteriaBuilder, filter.getSurname()));
predicates.add(peselPredicate(personDetailsJoin, criteriaBuilder, filter.getPesel()));
predicates.removeAll(Collections.singleton(EMPTY_PREDICATE));
query.orderBy(List.of(criteriaBuilder.asc(namePath), criteriaBuilder.asc(surnamePath))).distinct(true);
return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
};
}
When I try search results I can see an error:
ORA-01791: not a SELECTed expression
The problem is related to generated sql by JpaSpecificationExecutor.
It looks like this:
select
*
from
( select distinct pv.person_id
from
personview pv
inner join
persondetailsview pdv on pv.person_id=pdv.person_id
where
1=1
order by
pdv.name asc,
pdv.surname asc )
where
rownum <= ?
In Select clausule should be added name and surname then it would work, but I don't know how to do this in Specification. Without distinct query works, but i don't have duplicates.
Please for help.
From the error ORA-01791: not a SELECTed expression, you want to add the field to the select or remove the distinct with this :
query.distinct(false);
If you want to keep the distinct, have a look there :
https://stackoverflow.com/a/53549880/2641426

HQL syntax error : 'NHibernate.Hql.Ast.ANTLR.QuerySyntaxException'

As a beginner in HQL , I have a SQL query that I'm trying to transform into hql.
select * from (
   select *
   from CORRELATION_VUE
   where film = v_oldidfilm and FILM2 not in (
                           select c.idfilm
                           from cotes c
                           where idclient = v_idclient)
   order by CORRELATION desc
 
 )
 where rownum <= 3;
So in HQL I'm trying this :
ISession s = NHibernateHelper.GetCurrentSession();
ITransaction tx = s.BeginTransaction();
IQuery query = s.CreateQuery(
#"select u from (
select u from vueCorreliser u
where u.film = :idfilm
and u.FILM2 not in (
select c.idfilm from cote c
where c.idclient = :idclient)
order by u.CORRELATION desc)
where rownum <= 3; ")
.SetInt32("idfilm", idfilm)
.SetInt32("idclient", idclient);
IList<Film> result = query.List<Film>();
tx.Commit();
return result;
But I'm receiving a syntax error on the CreateQuery line.
What did I do wrong?
Thank you
Though I consider this a duplicate of this other question from you, here is a separate, more explicit answer here.
hql does not support sub-queries in from statement. (It supports them in other statements, such as in where conditions.) You have to rewrite your query without the sub-query in the from.
Your sub-query seems to be there only for limiting rows count. Remove the row limit from the query, and use .SetMaxResults(yourMaxRowCount) on the HQL query object instead.
There are no needs for the termination statement ; in HQL, and I do not know if it is supported. I think it is not, better remove it.
var query = s.CreateQuery(
#"select u from vueCorreliser u
where u.film = :idfilm
and u.FILM2 not in (
select c.idfilm from cote c
where c.idclient = :idclient)
order by u.CORRELATION desc")
.SetInt32("idfilm", idfilm)
.SetInt32("idclient", idclient)
.SetMaxResults(4);
That should fix the QuerySyntaxException.
By the way, your usage pattern of transaction is not safe. When using locally scoped transactions, always nest them in using for ensuring they are properly closed.
using (var tx = session.BeginTransaction())
{
...
tx.Commit();
return result;
}
Even in case of failure, the transaction will then always be disposed, which causes it to rollback if it were still ongoing.

JpaRepository: Spring Sort for runtime query variabels

There is my plain sql query:
SELECT id, title,
IF(o.fixed_on_top = 1 AND o.fixing_on_top_day_counter > 5, 1 ,0) actual_fixed_on_top
FROM orders o
ORDER BY actual_fixed_on_top DESC, publication_date DESC;
How can I perform sorting like this on JpaRepository?
Maybe using Criteria API?
But I dint find any examples..
Thanks!
EDIT:
ok, studied different ways, and convinced that it cant be implemented through Criteria API (but it is a pity)
One working variant: Native SQL Query, i am sure.
You can do it by using the QueryDslPredicateExecutor which provides the following two method:
Iterable<T> findAll(Predicate predicate, OrderSpecifier<?> ... orderSpecifiers);
Page<T> findAll(Predicate predicate, Pageable pageable);
The PageRequest class implements Pageable and allows you to specified the sorting you want.
You could also add a Pageable parameter in a #Query annotated method on a regular JpaRepository and Spring Data Jpa will do the rest, for example:
#Query("select e from SomeEntity e where e.param1 = :param1")
public Page<SomeEntity> findSome(#Param("param1") String param1, Pageable pageable);
(sorry cannot comment yet)
I recently had the same issue.
The only solution worked for me, is to specify the order on the relationship.
I don't see a relationship in your query
example:
#OneToMany
#OrderBy("date")
...
Spring data jpa does understand order by see doc
findByAgeOrderByLastnameDesc() will be parsed into where x.age = ?1 order by x.lastname desc clause.
I see your case a bit complicated, but you can do JQPL with #Query annotation, Sample:
#Query("SELECT o FROM Order o WHERE write your clause ORDER BY o.something desc")
public Order findByCustomPK(#Param("paramIfNeeded"));
I found the solution:
public class MyEntitySpecifications {
public static Specification<MyEntity> GetByPageSpecification() {
return new Specification<MyEntity>() {
#Override
public Predicate toPredicate(Root<MyEntity> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
Expression fixingExpr = cb.greaterThan(root.get(MyEntity_.fixingDueDate), new DateTime(DateTimeZone.UTC));
cq.orderBy(new OrderImpl(cb.selectCase().when(fixingExpr, 1).otherwise(0), false));
return cb...;
}
};
}
}
The main idea is using case expression instead of simple logical.
plain sql equuivalent is:
select ...
from my_entity e
where ...
order by case when e.fixing_due_date > now() then 1 else 0 end desc
So we can build dynamic queries with criteria api specifications as well.
No direct access to EntityManager, no plain sql.

Entity framework join with a subquery via linq syntax

I'm trying to translate a sql query in linq sintax, but I'm having big trouble
This is my query in SQL
select * FROM dbo.ITEM item inner join
(
select SUM([QTA_PRIMARY]) QtaTotale,
TRADE_NUM,
ORDER_NUM,
ITEM_NUM
from [dbo].[LOTTI]
where FLAG_ATTIVO=1
group by [TRADE_NUM],[ORDER_NUM],[ITEM_NUM]
)
TotQtaLottiGroupByToi
on item.TRADE_NUM = TotQtaLottiGroupByToi.TRADE_NUM
and item.ORDER_NUM = TotQtaLottiGroupByToi.ORDER_NUM
and item.ITEM_NUM = TotQtaLottiGroupByToi.ITEM_NUM
where item.PRIMARY_QTA > TotQtaLottiGroupByToi.QtaTotale
and item.FLAG_ATTIVO=1
How can I translate into linq sintax?
This approach doesn't work
var res= from i in context.ITEM
join d in
(
from l in context.LOTTI
group l by new { l.TRADE_NUM, l.ORDER_NUM, l.ITEM_NUM } into g
select new TotQtaByTOI()
{
TradeNum = g.Key.TRADE_NUM,
OrderNum = g.Key.ORDER_NUM,
ItemNum = g.Key.ITEM_NUM,
QtaTotale = g.Sum(oi => oi.QTA_PRIMARY)
}
)
on new { i.TRADE_NUM, i.ORDER_NUM, i.ITEM_NUM} equals new { d.TradeNum, d.OrderNum, d.ItemNum }
I get this error
The type of one of the expressions in the join cluase is incorrect. Type inference failed in the call to 'Join'
Can you help me with this query?
Thank you!
The problem is Anonymous Type comparison. You need to specify matching property names for your two anonymous type's properties (e.g. first, second, third)
I tried it out, here's an example: http://pastebin.com/hRj0CMzs

HQL / JPQL - Nested select on FROM

I try to convert my SQL query into HQL or JPQL (I want to benefit of the object mapping).
My SQL Request is :
SELECT *
FROM (SELECT bde, MAX(creation_date)
FROM push_campaign GROUP BY bde) temp,
push_campaign pc where pc.bde = temp.bde and pc.creation_date = temp.creation_date;
I try (unsuccessfully) to convert it in JPQL with :
select pc
from (select bde, max(creationDate)
from PushCampaign group by bde) temp,
PushCampaign pc
where pc.bde = temp.bde and pc.creationDate = temp.creationDate
But I got raised :
IllegalArgumentException occured :
org.hibernate.hql.ast.QuerySyntaxException: unexpected token: ( near
line 1, column 16 [select pc from (select id, max(creationDate) from
models.PushCampaign group by bde) temp, models.PushCampaign pc where
pc.id = temp.id]
I read the nested select can only be in select or where clause.
Do you have workarounds to keep the request and benefit of object-mapping ?
Not possible with JPQL or HQL in a single request.
To do this in a single request I propose this :
String campaignToLaunch = "select pc.* from PushCampaign pc ..."
//SQL request which return a resultset compatible with the models.PushCampaign class
Class className = Class.forName("models.PushCampaign");
List<PushCampaign> result = JPA.em()
.createNativeQuery(campaignToLaunch,className)
.getResultList();
this should achive similar results
select pc
from PushCampaign pc
where pc.creationDate =
(select max(creationDate) from PushCampaign inner where inner.bde = pc.bde)
A simple solution could be:
servlet
{
Query q = entityManager.createNativeQuery("SQL");
List<> li = q.getResultList();
#PersistenceContext(unitName="UNIT")
private EntityManager entityManager;
}