How to use JPA Query to insert data into db? - java

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

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);

namedParameterJdbctemplate update with more than one fields to update

Trying to update multiple column values in a table.
What I am missing, a little help!
The dao method is like...
The dao class Plan has all the fields populated with appropriate data.
public void updatePlan(Plan plan) {
SqlParameterSource mapSqlParameterSource = new MapSqlParameterSource().addValue("id", plan.getId())
.addValue("plan_name", plan.getPlan())
.addValue("price_category", plan.getPrice_category())
.addValue("updated_by", subscriptionPlan.getId());
String UPDATE_PLAN = "UPDATE plan_table SET(plan_name= :plan_name, price_category= :price_category, updated_by= :id) where id=:id)";
SqlParameterSource parameterSource = new BeanPropertySqlParameterSource(subscriptionPlan);
namedParameterJdbcTemplate.update(UPDATE_PLAN, mapSqlParameterSource);
}
The error is...(MySQL database - 5.6.43, Workbench - 6.3.9)
org.springframework.jdbc.BadSqlGrammarException:
PreparedStatementCallback; bad SQL grammar [update webstat_plan set (plan_name= ?, price_category= ?, updated_by= ?) where id=?)]; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax....
Issue is with your SQL Query.
Parenthesis is not required while updating the table.
Update your query with
UPDATE plan_table SET plan_name= :plan_name, price_category= :price_category, updated_by= :id where id=:id

how to fetch last column of the selected table using hibernate?

i am trying to fetch the id of last column in descending order.
the query which returns last column is
select id from(select id from challan
order by id desc) where ROWNUM=1;
now i am trying to do same thing using hibernate.
public long getIdOnChallanTable() {
session = sessionFactory.openSession();
trans = session.beginTransaction();
Query<Object[]> query = session.createNativeQuery("select id
from(select id from challan order by id desc) where ROWNUM=1;");
Long value = 0L;
List<Object[]> list = query.getResultList();
for ( Object lst : list){
Object[] objects =(Object[]) lst;
value=(Long)(objects[0]);
}
return value;
}
and the error is:
2017-07-26 12:37:36 [http-nio-7080-exec-1] WARN :: SQL Error: 911, SQLState: 22019
2017-07-26 12:37:36 [http-nio-7080-exec-1] ERROR:: ORA-00911: invalid character
update error javax.persistence.PersistenceException:
org.hibernate.exception.SQLGrammarException: could not extract ResultSet
You don't need the semicolon at the end of the query and please use proper whitespacing. In the FROM clause, you don't have the whitespace between the subquery and the FROM keyword.
Note: don't forget to commit/rollback the transaction at the end and handle the exceptions as well. I hope this was just a sketch to show us the problem and not a code from a real world application.

Trouble when using clase WHERE ... IN (list)

I'm having trouble when trying to retrieve from database using Hibernate. What I'm trying to do is to retrieve questions from the database (using Hibernate with HSQLDB) where the Tag tag is contained in the question list. Here is the error:
06-Jan-2017 19:43:26.021 WARN [http-apr-8080-exec-4] org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions SQL Error: -5585, SQLState: 42585 06-Jan-2017 19:43:26.021 ERROR [http-apr-8080-exec-4] org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions malformed numeric constant: .
Here the query:
Query query = session.createQuery("FROM Question q WHERE (:someTag) in (q.tagList) ORDER BY (q.creationDate) DESC").setParameter("someTag", tag).setMaxResults(amount);
And here the complete method:
public static List<Question> list(Tag tag, int amount){
Session session = HibernateUtil.getSession();
Query query = session.createQuery("FROM Question q WHERE (:someTag) in (q.tagList) ORDER BY (q.creationDate) DESC").setParameter("someTag", tag).setMaxResults(amount);
return query.list();
}
You need to use elements clause if you are trying to check whether a list contains an element, in this case, the query would look like this:
"FROM Question q WHERE :someTag in elements(q.tagList) ORDER BY (q.creationDate) DESC"

How do I convert this JPQL to CriteriaBuilder on H2?

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

Categories