I have a query that uses projections, it works well as long as the return type is List, but it stops working after adding pagination.
Here is the the working code:
#Query("SELECT DISTINCT \n" +
" new com.mycompany.dto.MyDto(me.property1, me.property2, ...) \n" +
"FROM MyEntiry me...")
List<MyDto> findEntities();
I need to extend it adding pagination, so I change it to:
#Query("SELECT DISTINCT \n" +
" new com.mycompany.dto.MyDto(me.property1, me.property2, ...) \n" +
"FROM MyEntiry me...")
Page<MyDto> findEntities(Pageable pageable);
Once I do that the context starts failing because while parsing it inserts select count(me) between SELECT and FROM statements so that the query become invalid:
SELECT DISTINCT
new com.mycompany.dto.MyDto(me.property1, me.property2, ...)
select count(me) FROM com.mycompany.MyEntiry me ...
The context fails with the following exception:
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException:
unexpected token: select near line 3, column 1 [SELECT DISTINCT new
com.mycompany.dto.MyDto(me.property1, me.property2, ...) select
count(me) FROM com.mycompany.MyEntiry me ...]
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:74)
at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:91)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:291)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:186)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:141)
at org.hibernate.engine.query.spi.HQLQueryPlan.(HQLQueryPlan.java:115)
at org.hibernate.engine.query.spi.HQLQueryPlan.(HQLQueryPlan.java:77)
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:153)
at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:553)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:662)
... 88 more
Question: How to make it work? Is it Spring Data bug?
Note:
The query I added is oversimplified, my real query in fact gathers different values from different tables and I can't implement it without projections
I'm using Spring Boot 1.5.8.RELEASE
Try to use 'native' Spring Data JPA projections.
This should work well:
public interface MyProjection {
String getProperty1();
//...
}
Page<MyProjection> getDistinctAllBy(Pageable pageable);
But, if your query joins many tables you cannot use the pagination without some pain (for example: 1, 2)
UPDATED
Try to add parameter countQuery to #Query annotation:
#Query(value = "select ...", countQuery = "select count(me) from MyEntiry me")
Page<MyDto> findEntities(Pageable pageable);
Related
As a programming student, I'm discovering Java (11) & Springboot.
In the application I'm developing, I would like to have a top-sellers list.
It is clear to me how to collect this data in SQL - the query is working effectiv, but using the JPA Repositories & native query it isn't...
Why do I get the error to include the Id column in the "group by" part? If I do this, the result is offcourse not what I was looking for ...
#Query(value = "SELECT *, SUM(od.numberofproducts) AS sold, SUM(p.price * od.numberofproducts) AS revenue FROM OrderDetail od JOIN product p ON p.id = od.productid GROUP BY od.productid ORDER BY sold DESC limit 10", name = "getTopSellersList", nativeQuery=true)
I gone through this in stackoverflow for the pagination in native queries, No error while returning records. It is giving all records instead of taking parameter value in pageable ex: iam passing these pageSize(5 or 4) and pageNo(0) to pageable parameter.
#Query(value = "select * from job_post where comp_addr_ref_id not in"
+ "(select mapping_id from company_address where ref_company_id in"
+ "(select mapping_id from company where mapping_id in"
+ "(select comp_ref_id from comp_visibility where is_comp_visible=0 and login_ref_id=:mappingId)))"
+ " order by created_date desc \n#pageable\n", nativeQuery = true)
public List<JobPost> findUserBlockedCompanies(String mappingId, Pageable pageable);
If you're using Spring Boot 2.0 or higher, try to delete \n#pageable\n section.
If you use PostgreSql and MySql change the value \n#pageable\n to
?#{#pageable}
If it still doesn't work you can enable logging of SQL statements using spring.jpa.show-sql=true in your application.properties
I had similar issue.
If you are using Spring Data prior to 2.0.4, then you can try to replace
\n#pageable\n
with
\n /* --#pageable */ \n
This works for Postgres and Oracle.
P.S. In Spring Data 2.0.4+ you can completely remove this pageable token from query as it's not required anymore (https://jira.spring.io/browse/DATAJPA-928)
See also Spring Data and Native Query with pagination
I have fixed in oracle. My way is:
1-> write order by created_date OFFSET :offset ROWS FETCH NEXT :pageSize ROWS ONLY
to your main query
2-> create count query for your main query
3-> and you can unit your datas with new PageIml<>(mainQueryResult, PageRequest.of(page,size), countQueryResult);
it works for all dbs
I want to be able to use inner conditions withing spring data jpa search query:
#Query("SELECT u FROM User u "
+ "WHERE (:isBlocked IS NULL OR (u.unblockDate IS NOT NULL OR u.unblockDate > CURRENT_DATE) = :isBlocked)" )
Page<User> filter(#Param("isBlocked") Boolean isBlocked,
Pageable pageable);
such logic works fine in sql but I can't make it work with spring-data-jpa. Is it correct syntax in spring data jpa?
UPDATE I'm getting the following exception:
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected AST node: OR near line 1, column 107 [SELECT u FROM User u WHERE (:isBlocked IS NULL OR (u.unblockDate IS NOT NULL OR u.unblockDate > CURRENT_DATE) = :isBlocked)]
I've recently upgrade from hibernate 3.5 to 4.3.11 with Spring 4.3.9 Before the upgrade everything was working fine. After the upgrade I get this error.
Environment:
Java 8,
Tomcat 7.0.23,
Hibernate 4.3.11,
Spring 4.3.9,
MSSQL Server 2008,
While executing the following sql query through hibernate, we are getting list of null object with correct size in the list but object are null.
Query:
select DISTINCT(HIERARCHY_ID) from BASETYPE_HIERARCHY_MAPPING
where BASETYPE_ID IN (select BASETYPE_ID from BASETYPE_GROUP_MAPPING
where GROUP_ID IN (select GROUP_ID from USER_GROUP_MAPPING where USER_ID like(select ID from USER where USERID='7')))
Java Code:
String sqlQuery="select DISTINCT(HIERARCHY_ID) from BASETYPE_HIERARCHY_MAPPING where BASETYPE_ID IN "
+ "(select BASETYPE_ID from BASETYPE_GROUP_MAPPING where GROUP_ID IN "
+ "(select GROUP_ID from USER_GROUP_MAPPING where USER_ID=(select ID from USER where USERID=:userId)))";
Query query = session.createSQLQuery(sqlQuery);
query.setParameter("userId", userId);
List<String> typeId = query.list();
In result list of null objects.I have found similar type of issue for HQL(solution was mistake in mapping) but its simple sql query.
Similar Issue reference link:
Hibernate returns list of nulls although executed SQL returns values
You are getting null because you column in not getting mapped here. You can do this step here.
Make a class to get HIERARCHY_ID, like this
public class ABC{
private long id;
}
and then write query like this
#Query("SELECT new com.abc.abc.ABC (t.id) from table t")
This will give you list of ABC object and I think it will work.
Solved the problem using hibernate scalar, by specifying the return type of column in query.
addScalar()
Following changes are done in java code to solve the issue.
String sqlQuery="select DISTINCT(HIERARCHY_ID) from BASETYPE_HIERARCHY_MAPPING where BASETYPE_ID IN "
+ "(select BASETYPE_ID from BASETYPE_GROUP_MAPPING where GROUP_ID IN "
+ "(select GROUP_ID from USER_GROUP_MAPPING where USER_ID=(select ID from USER where USERID=:userId)))";
Query query = session.createSQLQuery(sqlQuery).addScalar("HIERARCHY_ID", StringType.INSTANCE);
query.setParameter("userId", userId);
List<String> typeId = query.list();
But in our project lot of sql queries used, so I need to change in all queires any better soluation instead of this addScalar() or why its mandatory from hibernate 4, it was working fine in 3.5
I have 3 tables in Oracle DB which relationship is #ManyToMany. So I have 2 significant tables and one for mappings.
I create a classes with name (if you want I can show my classes) named Entities, Keywords (I understand that naming is not correct but this is not my project I only do optimizations).
I use hibernate version 4.3.4.
I write query like this:
session = HibernateUtil.getSessionFactory().openSession();
String sql = "SELECT DISTINCT r FROM Rules r, Entities e " +
" WHERE r.entities = e.rules " +
" AND e IN :entities ";
Query query = session.createQuery(sql);
query.setParameterList("entities", entitiesList);
List<Rules> rulesList = query.list();
BUT! Hibernate generate strange SQL
Hibernate:
select
rules0_.rule_id as rule_id1_11_,
rules0_.rule as rule2_11_
from
rules rules0_,
entities entities1_,
rules_entities entities2_,
entities entities3_,
rules_entities rules4_,
rules rules5_
where
rules0_.rule_id=entities2_.rule_id
and entities2_.entity_id=entities3_.entity_id
and entities1_.entity_id=rules4_.entity_id
and rules4_.rule_id=rules5_.rule_id
and .=.
and (
entities1_.entity_id in (
? , ? , ? , ?
)
)
When I try to execute this query I receive that error:
java.sql.SQLException: ORA-00936: missing expression
When I copy this query to OracleDevepoler he didn`t like this expression "and .=.". Without that query executes correct.
What am I doing wrong ?
Maybe you used bad join in your query? From context i conclude that you should use something like that:
"SELECT DISTINCT r FROM Rules r inner join r.entities e " +
" WHERE e IN :entities ";
I think the correct query could be
select distinct e.rules from Entities where e.entityId in :entities
This is if Keywords is your join table and you have a collection of rules in Entities
If it isn't, can you show the mappings please, it could help.