How do I convert this JPQL to CriteriaBuilder on H2? - java

I'm trying to convert this query
#Query( "select l from Log l order by l.created desc, l.entry asc " )
Page<Log> findAllCustomJpql( Pageable pageable );
which generates this sql
Hibernate: select count(log0_.id) as col_0_0_ from log log0_
Hibernate: select log0_.id as id1_0_, log0_.created as created2_0_, log0_.entry as entry3_0_ from log log0_ order by log0_.created desc, log0_.entry asc limit ?
to a criteria builder query, using specifications
#RequestMapping( method = RequestMethod.GET, path = "spec")
Page<Log> getLogsBySpecification( final Pageable pageable ) {
return repository.findAll( ( root, query, cb ) -> {
query.orderBy(
cb.desc( root.get( "created" ) ),
cb.asc( root.get( "entry" ) )
);
return null;
}, pageable);
}
which is doing the following
2015-10-17 19:33:40.720 WARN 10498 --- [nio-8080-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 90016, SQLState: 90016
2015-10-17 19:33:40.721 ERROR 10498 --- [nio-8080-exec-6]
o.h.engine.jdbc.spi.SqlExceptionHelper : Column "LOG0_.ENTRY" must be in the GROUP BY list; SQL statement:
select count(log0_.id) as col_0_0_ from log log0_ order by log0_.created desc, log0_.entry asc [90016-188]
2015-10-17 19:33:40.750 ERROR 10498 --- [nio-8080-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: could not extract ResultSet; nested exception is org.hibernate.exception.GenericJDBCException: could not extract ResultSet] with root cause
org.h2.jdbc.JdbcSQLException: Column "LOG0_.ENTRY" must be in the GROUP BY list; SQL statement:
select count(log0_.id) as col_0_0_ from log log0_ order by log0_.created desc, log0_.entry asc [90016-188]
I personally think the sql is valid, if ill advised, but doesn't seem to be valid for h2. How can I correct my criteria in order to generate the results I want?

This is really not the same query but I do believe it comes to the same effect.
#RequestMapping( method = RequestMethod.GET, path = "spec" )
Page<Log> getLogsBySpecification( final Pageable pageable ) {
return repository.findAll( ( root, query, cb ) -> {
query.orderBy(
cb.desc( root.get( "created" ) ),
cb.asc( root.get( "entry" ) )
);
query.groupBy( root.get( "id" ) );
return null;
}, pageable );
}
I am kind of wondering if the fact that the specification continues to apply the order by is a bug... ultimately this seems related to this bug

Related

I using #Query and Pageable has error: Variables are only allowed when ordering by an expression referencing a column name

I tried to query:
#Query(value = "SELECT * FROM BookingOffice WHERE tripId in (select Trip.tripId from Trip Where Trip.desfination like ?#{#desfination}) ORDER BY ?#{#pageable}",
countQuery = "SELECT COUNT(*) FROM BookingOffice WHERE tripId in (select Trip.tripId from Trip Where Trip.desfination like ?#{#desfination})",
nativeQuery = true)
public Page<BookingOffice> findAllByTrip(String desfination, Pageable pageable);
My PageRequest:
Sort sort = new Sort(Direction.DESC, "officeId");
PageRequest pageRequest = new PageRequest(page, 7, sort);
Hibernate Query on runtime
**> Hibernate:
SELECT
*
FROM
BookingOffice
WHERE
tripId in (
select
Trip.tripId
from
Trip
Where
Trip.desfination like ?
)
ORDER BY
?,
officeId desc offset 0 rows fetch next ? rows only**
ERROR:
May 17, 2020 12:41:29 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/CarPark] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet] with root cause
com.microsoft.sqlserver.jdbc.SQLServerException: The SELECT item identified by the ORDER BY number 1 contains a variable as part of the expression identifying a column position. Variables are only allowed when ordering by an expression referencing a column name.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:254)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1608)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:578)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:508)
at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7240)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2869)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:243)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:218)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery(SQLServerPreparedStatement.java:434)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:60)
at org.hibernate.loader.Loader.getResultSet(Loader.java:2171)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1934)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1896)
at org.hibernate.loader.Loader.doQuery(Loader.java:936)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:339)
at org.hibernate.loader.Loader.doList(Loader.java:2693)
at org.hibernate.loader.Loader.doList(Loader.java:2676)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2510)
at org.hibernate.loader.Loader.list(Loader.java:2505)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:338)
at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:2262)
at org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.java:1069)
at org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.java:173)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1529)
at org.hibernate.query.Query.getResultList(Query.java:165)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498) ....
Please help me! Thanks
I think the problem is that you are using Pageable object in order by clause of your select query. It expects a column name for ordering the results.
Please try like below, I have done same kind of implementation in my project and it's working fine.
#Query(value = "SELECT * FROM BookingOffice WHERE tripId in (select Trip.tripId from Trip Where Trip.desfination like %?1%}))",
nativeQuery = true)
public Page<BookingOffice> findAllByTrip(String desfination, Pageable pageable);

QuerySyntaxException: unexpected token:Using criteria builder to make a difference between dates in postgresql

I'm trying to make the following query using Jpa Specification, I'm using Postgresql:
select * from record rec inner join record_history rec_hist on rec.id=rec_hist.official_record_id and (rec_hist.state=rec.state) where
extract(epoch from (current_timestamp - rec_hist.create_date)) > rec_hist.standard_duration
In the “toprediacte” method I have written the following code using criteria builder
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
Join historyJoin = root.join("recordHistory");
historyJoin.on(cb.equal(historyJoin.get("state"), root.get("state")));
Expression<Timestamp> epoch = cb.function(
"epoch",
Timestamp.class,
new UnitExpression(null, String.class, "from"),
historyJoin.<Timestamp>get("createDate"));
Expression<Integer> extract = cb.function(
"extract",
Integer.class,
epoch);
Predicate durationPredicate = cb.greaterThan(historyJoin.<Integer>get("standardDuration"), extract);
return cb.and(cb.and(super.toPredicate(root, cq, cb)), durationPredicate);
}
If I run this code I receive the following exception
QuerySyntaxException: unexpected token: , near line 1, column 323 [select generatedAlias0 from Record as generatedAlias0 inner join generatedAlias0.recordHistory as generatedAlias1 with generatedAlias1.state=generatedAlias0.state where ( 1=1 ) and ( generatedAlias1.standardDuration>function('extract', function('epoch', from, generatedAlias1.createDate)) )]]
Can you help me figure out how to implement this query?
Thanks

How to use JPA Query to insert data into db?

I have a problem with my prepared statement but i can not figure out where the error is. I am trying to insert a URI link into the database.
#Repository
public interface LoggerDao extends CrudRepository<Logger, Long> {
#Query("select t from Logger t where t.user.id=?#{principal.id}")
List<Logger> findAll();
#Modifying
#Query(value = "insert into Logger t (t.redirect, t.user.id) VALUES (:insertLink,?#{principal.id})", nativeQuery = true)
#Transactional
void logURI(#Param("insertLink") String insertLink);
Error
2017-03-11 19:52:59.157 WARN 65154 --- [nio-8080-exec-8] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 42001, SQLState: 42001
2017-03-11 19:52:59.157 ERROR 65154 --- [nio-8080-exec-8] o.h.engine.jdbc.spi.SqlExceptionHelper : Syntax error in SQL statement "INSERT INTO LOGGER T[*] (T.REDIRECT, T.USER.ID) VALUES (?,?) "; expected "., (, DIRECT, SORTED, DEFAULT, VALUES, SET, (, SELECT, FROM"; SQL statement:
insert into Logger t (t.redirect, t.user.id) VALUES (?,?) [42001-190]
2017-03-11 19:52:59.181 ERROR 65154 --- [nio-8080-exec-8] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement; SQL [insert into Logger t (t.redirect, t.user.id) VALUES (?,?)]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement] with root cause
org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "INSERT INTO LOGGER T[*] (T.REDIRECT, T.USER.ID) VALUES (?,?) "; expected "., (, DIRECT, SORTED, DEFAULT, VALUES, SET, (, SELECT, FROM"; SQL statement:
insert into Logger t (t.redirect, t.user.id) VALUES (?,?) [42001-190]
at org.h2.engine.SessionRemote.done(SessionRemote.java:624) ~[h2-1.4.190.jar:1.4.190]
at org.h2.command.CommandRemote.prepare(CommandRemote.java:68) ~[h2-1.4.190.jar:1.4.190]
at org.h2.command.CommandRemote.<init>(CommandRemote.java:45) ~[h2-1.4.190.jar:1.4.190]
at org.h2.engine.SessionRemote.prepareCommand(SessionRemote.java:494) ~[h2-1.4.190.jar:1.4.190]
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1188) ~[h2-1.4.190.jar:1.4.190]
at org.h2.jdbc.JdbcPreparedStatement.<init>(JdbcPreparedStatement.java:72) ~[h2-1.4.190.jar:1.4.190]
at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:276) ~[h2-1.4.190.jar:1.4.190]
at org.apache.tomcat
I managed to solve the issue. I added an id to the parameters so that i can pass in the id of the user, using Principal in the controller.
#Repository
public interface LoggerDao extends CrudRepository<Logger, Long> {
#Query("select t from Logger t where t.user.id=?#{principal.id}")
List<Logger> findAll();
#Modifying
#Query(value = "insert into Logger (redirect,user_id) VALUES (:insertLink,:id)", nativeQuery = true)
#Transactional
void logURI(#Param("insertLink") String insertLink, #Param("id") Long id);
There is a way to do inserts using obj (not native) queries (using #Query & #Modifying) but it depends on the db you're using. Below worked for me in Oracle (using Dual table):
#Repository
public interface DualRepository extends JpaRepository<Dual,Long> {
#Modifying
#Query("insert into Person (id,name,age) select :id,:name,:age from Dual")
public int modifyingQueryInsertPerson(#Param("id")Long id, #Param("name")String name, #Param("age")Integer age);
}
Here's a link which shows at the bottom which db's support select stmts without a from clause : http://modern-sql.com/use-case/select-without-from

Want to convert and SQL to Hibernate Query Language

I have a requirement where I have to convert an SQL to HQL.
The SQL query is as follows:
select RT.tableNumber, temp.confirmationNumber from ReservationTable RT, (select R.tableNumber, R.confirmationNumber from Reservation R where R.date = 'someDate' and R.time = 'someTime' and R.reservationStatus = 'CONFIRMED') as temp where RT.tableNumber = temp.tableNumber and RT.tableNumber = 'someTableNumber' ;
I tried converting it to the following HQL:
select RT.tableNumber, temp.confirmationNumber from ReservationTable RT, (select R.tableNumber, R.confirmationNumber from Reservation R where R.date = :param1 and R.time = :param2 and R.reservationStatus = 'CONFIRMED') as temp where RT.tableNumber = temp.tableNumber and RT.tableNumber = :param3";
But when I run this HQL through Eclipse, I get the below error lines:
ERROR: line 1:102: unexpected token: (
ERROR: line 1:146: unexpected token: from
SEVERE: Servlet.service() for servlet [dispatcher] in context with
path [/RRSRestApp] threw exception [Request processing failed; nested
exception is org.hibernate.hql.internal.ast.QuerySyntaxException:
unexpected token: ( near line 1, column 102 [select RT.tableNumber,
temp.confirmationNumber from
com.kartik.restaurant.model.ReservationTable RT, (select
R.tableNumber, R.confirmationNumber from
com.kartik.restaurant.model.Reservation R where R.date = :param1 and
R.time = :param2 and R.reservationStatus = 'CONFIRMED') as temp where
RT.tableNumber = temp.tableNumber and RT.tableNumber = :param3; ]]
with root cause org.hibernate.hql.internal.ast.QuerySyntaxException:
unexpected token: ( near line 1, column 102 [select RT.tableNumber,
temp.confirmationNumber from
com.kartik.restaurant.model.ReservationTable RT, (select
R.tableNumber, R.confirmationNumber from
com.kartik.restaurant.model.Reservation R where R.date = :param1 and
R.time = :param2 and R.reservationStatus = 'CONFIRMED') as temp where
RT.tableNumber = temp.tableNumber and RT.tableNumber = :param3; ]
Can anyone help me with this?
According to hibernate documentation HQL subqueries can occur only in the select or where clauses.
for more detail please follow hibernate documentation

HQL transformation

I am a newbie with HQL and I am trying to do this :
select count(T) from (
select inscription, max(wrd_step) as max
from table aa
where rd_context = ?
group by inscription
) as T
where T.max = ?
The error is :
Caused by: org.hibernate.hql.ast.QuerySyntaxException: unexpected token: ( near line 1, column 21 [select count(T) from( select inscription, max(wrd_step) from table aa where rd_context = ? group by inscription) as T where T.max = ?]
Thanks
EDIT :
The query in HQL is :
SELECT count(distinct inscription)
FROM Entity
WHERE inscription in (
select distinct inscription
from Entity
where rd_context = ?
group by inscription
having max(wrd_step) = ?
)
Hibernate documentation states:
Note that HQL subqueries can occur only in the select or where clauses.
http://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html_single/#queryhql-subqueries
But assuming table is a mapped entity (is it?), you can do this (not tested):
select count(aa)
from table aa
where rd_context = :param1
group by inscription
having max(wrd_step) = :param2

Categories