Iam working with spring boot and jpa repository I want get the last 2 records from database using hql query.
I have writen the follwoing query but its not working.
#Query("select news from(select news from NewsDTO news order by news.newsId desc limit 2) sub order by news.newsId asc")
It is throwing the folloing exception
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ( near line 1, column 17 [select news from(select news from com.mer.aigs.dto.news.NewsDTO news order by news.newsId desc limit 2) sub order by news.newsId asc]
JPQL doesn't support LIMIT clause natively. With Spring Data JPA, however, you can use
combination of ORDER BY .. DESC and Pageable to achieve what you intend to. Refer this for detailed information https://www.logicbig.com/tutorials/spring-framework/spring-data/pagination.html
limit keyword is not supported by hql (it's even different across different databases). You need to create a Query using entity manager and specify the maximal size:
em.createQuery("your query").setMaxResults(2).getResultList()
assuming you have entity manager injected:
#Autowired
private EntityManager em
This solution performs better than using Pageable.
As mentioned by #Kedar you cannot use LIMIT inside your JPQL query due to the database-specific nature. Therefore you need to use a NATIVE QUERY and replace the physical table name and column name for NewsDTO and newsId:
#Query(value = "select news from(select news from *NewsDTO* news order by *newsId* desc limit 2) sub order by *newsId* asc", nativeQuery = true)
This worked for me, where created is the timestamp column in the table:
repository.findAll(PageRequest.of(0, 2, Sort.by("created").descending())))
In my case, I wanted the result sorted by the created column.
Hope this helps someone.
Related
I want to get the number of results of a query in Spring Data Jpa, using a non-native #Query method. It consists of a basic group by plus a having clause.
My plain query looks like this (analogous example):
select count(*) from (
select 1 from table t
where t.field_a = 1
group by t.id
having count(*) = 2) a;
Since Hibernate 5 does not allow subqueries in the form clause, I have to find a workaround for that. The only one I found is very inefficient as per the query plan:
select count(*) from table t
where t.field_a = 1 and
2 = (select count(*) from table temp where temp.id = t.id);
Is there a way to write a Spring Data JPA query that's as efficient as the first one? I can think of no solution rather than selecting the inner query and taking its size() in java, but that can produce issues due to a ton of redundant data passing through the network.
There is no easy solution to count the results of a subquery in JPA but the a workaround is proposed here https://arjan-tijms.omnifaces.org/2012/06/counting-rows-returned-from-jpa-query.html.
The principle is to build a native query based on the initial Jpa subselect query.
This does the job if you accept to count the elements in java !
Query q = em.createQuery(
"select 1 from table t where field_a = 1 " +
"group by t.id having count(*) = 2");
int count = q.getResultList().size();
(performances depending on the number of lines returned, but the projection is very light : 1)
I want to make dynamic query in which if particular parameter is sent, the Native query should filter the result based on it. In case it's null, it should not reflect the result.
I am using Spring Data JPA with Native query mechanism + Oracle DB
For String parameters this approach works fine
:email is null or s.email = :email
but for Integer parameters when they have value, the Query works but if the parameter is null the query fails with the error
Caused by: java.sql.SQLSyntaxErrorException: ORA-00932: inconsistent datatypes: expected NUMBER got BINARY
I am using the exactly the same approach for for Integer instead of String
I am wondering whether the problem is on my side or it's some kind of bug?
In Oracle DB it's not worked this way. A workaround is using JPQL like
SELECT s FROM Entity s WHERE :id is null OR s.id = COALESCE(:id, -1)
Or for native query use TO_NUMBER function of oracle
SELECT s FROM Entity s WHERE :id is null OR s.id = TO_NUMBER(:id)
I am trying to write a query to fetch list as this query is native sql query, all I need is to transform to spring jpql in which I am failing badly. if there is any link related to this please let me know
I am supposed to get list from this query. as this query is working fine with postgres console but when I even tried this with spring jpa as native query
it is showing results in console but not fetching in service layer [edit:] I mean not calculating any result set.
I am sure I am missing some important/small thing here.
below is the native postgres query
selcet t.id,count(*), count(*) filter (where t.status = 'DONE') from table t where t.id in ([list]) group by t.id
what Im trying is
SELECT t.id, count(t), count(t.id) where staus = 'DONE' from Table t where t.id in ([list]) group by t.id
edit: with constructor based query this is not even working
I am not even sure how to start this query
while being new to this I am not even able to start how to solve this.
Any hint, insight will be useful
I'm pretty new to hibernate and I was trying it out in one of my applications. I chose to use annotation session factory bean and my editor generated entity classes for each table from the DB which had named queries. hibernateTemplate.findByAll worked fine. But when I tried hibernateTemplate.findByNamedQuery("findById", "<some_id>"), it gave an error: java.lang.IndexOutOfBoundsException: Remember that ordinal parameters are 1-based. After a bit of googling, tried out multiple solutions:
Changed the namedQuery that was generated by editor from : #NamedQuery(name = "Table.findById", query = "SELECT u FROM Table t WHERE t.id = :id"), to : #NamedQuery(name = "Table.findById", query = "SELECT u FROM Table t WHERE t.id = ?") but got the same error.
Tried using hibernateTemplate.findByNamedParam but ended up getting error: java.lang.IllegalArgumentException: node to traverse cannot be null!
I can use hibernateTemplate.find() to achieve this but how do I use findByNamedQuery/Param methods to achieve the same since the documentation says these methods may be used to fetch records based on a field?
Updated
Error says:
ava.lang.String cannot be cast to com.test.test.classes.TblTaxType
what is happening is when I add the tag select distinct taxtcode error is appearing. But when I removed the select tag like FROM tblTaxType tbl_tax_type WHERE bfnsCode = ? everything is fine. What is the cause? this is my code:
String hql = "SELECT DISTINCT TAXT_CODE FROM tbl_tax_type WHERE BFNS_CODE = ?";
try {
setSession(HibernateUtil.getSession());
#SuppressWarnings("unchecked")
List <TblTaxType> resultList = getSession().createSQLQuery(hql)
.setString(0, bfnsCode)
.list();
Your entity is probably named TblTaxType, not tblTaxType. Case matters.
Side note: don't name sql an HQL query. SQL and HQL are different languages.
Solved it using GROUP BY instead by using DISTINCT.
String hql = "FROM TblTaxType tbl_tax_type WHERE bfnsCode = ? GROUP BY taxtCode";
Your query returns TAXT_CODE, this field is a property of your TblTaxType entity, so you can't cast one property (string) in your main entity. This is the reason of your error.
If you need complete entity you must change your query but DISTINCT is not useful in this case because if you extract complete entity, there's ID field (different for each row). If you want a first element, you can add in your query ORDER BY clause with LIMIT 1 (is MySql).
A solution with GROUP BY works only if you use MySql as DBMS because if you have Sql Server the correct behaviour of field list / group by is: a field in field list must be in GROUP BY cluse or must be in aggregate function.