Native query produces MySQL syntax error and unexpected result - java

In my application, when a User removes a Message, I need to remove the relationship between the 2 entities while keeping them intact. Hence, I tried to delete rows directly from the relationship table using the following ways:
1.
Query q = em.createNativeQuery("DELETE FROM User_Inbox WHERE User_USERNAME = :username AND Message_ID = :messageID");
q.setParameter("username", username);
q.setParameter("messageID", messageID);
q.executeUpdate();
2.
Query q = em.createNativeQuery("DELETE FROM User_Inbox WHERE User_USERNAME = :username AND Message_ID = :messageID");
q.setParameter("username", "'" + username + "'");
q.setParameter("messageID", "'" + messageID + "'");
q.executeUpdate();
The 1st and 2nd approaches produced the following exception:
Internal Exception: 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 to use near ':username AND
Message_ID = :messageID' at line 1
Error Code: 1064
3.
Query q = em.createNativeQuery("DELETE FROM User_Inbox WHERE User_USERNAME = ':username' AND Message_ID = ':messageID'");
q.setParameter("username", username);
q.setParameter("messageID", messageID);
q.executeUpdate();
The 3rd approach did not produce any exceptions. It went through normally. However, nothing was deleted from the User_Inbox table.
4.
Query q = em.createNativeQuery("DELETE FROM User_Inbox WHERE User_USERNAME = '" + username + "' AND Message_ID = '" + messageID + "'");
q.executeUpdate();
The 4th approach worked perfectly. The query went through smoothly and a record was deleted properly.
The last approach worked but the code doesn't look very neat to me. I'd be very grateful if someone could show me what I did wrong with the 1st three approaches.
UPDATE:
Based on the answer from D. Moore, I've just found out that named parameters cannot be used with native queries. This has been mentioned in this answer by Pascal Thivent.
Named parameters follow the rules for identifiers defined in Section
4.4.1. The use of named parameters applies to the Java Persistence query language, and is not defined for native queries. Only
positional parameter binding may be portably used for native
queries.

I agree that (4.) is certainly not the right way to be doing things. It's tedious and unsafe.
(3.) are working, but not producing the expected results since they have extra quotes.
As to why (1.) isn't working, you would want to look into the SQL that is being generated (I believe the settings are specific to the JPA system you are using). You seem to have the code correct, but the error implies that the parameters are not being substituted.
Do positional parameters do anything different?
Query q = em.createNativeQuery("DELETE FROM User_Inbox WHERE User_USERNAME = ?1 AND Message_ID = ?2");
q.setParameter(1, username);
q.setParameter(2, messageID);
q.executeUpdate();

Related

MySQL Syntax Issue when using Accounts.UUID AND UUID =, with two tables

I'm having issues when using this:
WARN 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 to use near 'WHERE Accounts.UUID = WarAccounts.UUIDAND Accounts.UUID = 'c7a00fe7-826d-46da-b4' at line 1
Here is the SQL:
SELECT
*
FROM
Accounts,
WarAccounts
WHERE
Accounts.UUID = WarAccounts.UUID
AND Accounts.UUID = ?
(Using prepared statements)
I'm very confused as to what is wrong with this to cause that issue, I've googled it but cannot find anything since this seems to be the correct way.
Server type: MySQL
Server version: 5.5.58-0ubuntu0.14.04.1 - (Ubuntu)
Wild ass guess:
In C# i would do this:
string query = "SELECT *" +
"FROM MYTABLE" +
"WHERE 1=1"
..to get your error..
Concat the string and you'll see the problem:
"SELECT *FROM MYTABLEWHERE 1=1"
The concatination should be:
string query = "SELECT * " +
"FROM MYTABLE " +
"WHERE 1=1 "
(see the spaces at the end of every line?)

hibernate hql - return updated rows id list after execute update query

I'm using Hibernate Query Language(HQL) with Oracle database in my Java spring MVC application. I have write an HQL update query in this way:
String hql = "update " + MyModel.class.getName() + " e set e.field = " + value + " where ..."
//Acquiring session
...
Query query = session.createQuery(hql);
int result = query.executeUpdate();
The executeUpdate() method returns number of updated rows. But I want to get a list of the ids of updated rows after executing the update query. Is there any way of doing this in HQL?
As far as I know there is no such functionality in JPA/Hibernate. But you can create native query and use native SQL. I do not know oracle, but in PostgreSQL I would write :
String sql = "update table set field = :values where ... returning id";
Query query = session.createNativeQuery(sql);
query.setParameter("value", value);
List ids = query.list();
May be oracle have similar functional and this will help you.
Blaze-Persistence, a library that works on top of JPA/Hibernate, adds support for this.
Here some more information about that: https://persistence.blazebit.com/documentation/core/manual/en_US/index.html#returning-from-update-statement

Delete from table on same select same table mariadb using jpa

I need delete from table on operation of same table .JPA query is
DELETE FROM com.model.ElectricityLedgerEntity a
Where a.elLedgerid IN
(SELECT P.elLedgerid FROM
(SELECT MAX(b.elLedgerid)
FROM com.model.ElectricityLedgerEntity b
WHERE b.accountId='24' and b.ledgerType='Electricity Ledger' and b.postType='ARREARS') P );
I got this error:
with root cause org.hibernate.hql.ast.QuerySyntaxException: unexpected
token: ( near line 1, column 109 [DELETE FROM
com.bcits.bfm.model.ElectricityLedgerEntity a Where a.elLedgerid IN (
SELECT P.elLedgerid FROM ( SELECT MAX(b.elLedgerid) FROM
com.bcits.ElectricityLedgerEntity b WHERE b.accountId='24'
and b.ledgerType='Electricity Ledger' and b.postType='ARREARS') P ) ]
at
org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:54)
at
org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:47)
at
org.hibernate.hql.ast.ErrorCounter.throwQueryException(ErrorCounter.java:82)
at
org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:284)
Same query is running on mysql terminal ,but this is not working with jpa .Can any one tell me how i can write this query using jpa .
I don't understand why do you use Pbefore the last parenthesis...
The following code is not enough ?
DELETE FROM com.model.ElectricityLedgerEntity a
Where a.elLedgerid IN
(SELECT MAX(b.elLedgerid)
FROM com.model.ElectricityLedgerEntity b
WHERE b.accountId='24' and b.ledgerType='Electricity Ledger' and
b.postType='ARREARS')
Edit for bypassing mysql subquery limitations :
The new error java.sql.SQLException: You can't specify target table 'LEDGER' for update in FROM clause
is known in mysql when you use it with JPA. It's one MySQL limitation.
A recent stackoverflow question about it
In brief, you cannot "directly" updated/deleted a table that you query in a select clause
Now I understand why your original query did multiple subqueries seemingly not necessary (while it was useful for mysql) and had a "special" syntax.
I don't know tricks to solve this problem in JPA (I don't use the MySQL DBMS for a long time now).
At your place, I would do two queries. The first where you select the expected max elLedgerid and the second where you could delete line(s) with the id retrieved in the previous query.
You should not have performance issues if your sql model is well designed, the sql indexes well placed and the time to access to the database is correct.
You cannot do this in a single query with Hibernate. If you want to delete the max row(s) with Hibernate you will have to do so in two steps. First, you can find the max entry, then you can delete using that value in the WHERE clause.
But the query you wrote should actually run as a raw MySQL query. So why don't you try executing that query as a raw query:
String sql = "DELETE FROM com.model.ElectricityLedgerEntity a " +
"WHERE a.elLedgerid IN (SELECT P.elLedgerid FROM " +
"(SELECT MAX(b.elLedgerid) FROM com.model.ElectricityLedgerEntity b " +
"WHERE b.accountId = :account_id AND b.ledgerType = :ledger_type AND " +
" b.postType = :post_type) P );";
Query query = session.createSQLQuery(sql);
query.setParameter("account_id", "24");
query.setParameter("ledger_type", "Electricity Ledger");
query.setParameter("post_type", "ARREARS");
Just want to extend existing answer:
In brief, you cannot "directly" updated/deleted a table that you query in a select clause
This was lifted with starting from MariaDB 10.3.1:
Same Source and Target Table
Until MariaDB 10.3.1, deleting from a table with the same source and target was not possible. From MariaDB 10.3.1, this is now possible. For example:
DELETE FROM t1 WHERE c1 IN (SELECT b.c1 FROM t1 b WHERE b.c2=0);

SQL Firebird implementation in java/ IBSQL

so tried to put that SQL code into my java-aplication:
SELECT DISTINCT
StRzImRo.Rohstoff, StRo.Bezeichnung,
CAST (SUM(BwLsImAt.Lieferungen * StRzImRo.Menge * StAt.PROD__REZEPTURGEWICHT / Coalesce(StRz.PARM__BEZUGSGROESSE,1)) AS NUMERIC (9,3)) Rohstoffverbrauch_Gesamt FROM BwLsImAt
JOIN StAt ON (StAt.IntRowId = BwLsImAt.Artikel)
JOIN StRz ON (StRz.IntRowId = StAt.PROD__REZEPTUR)
JOIN StRzImRo ON (StRzImRo.Master = StRz.IntRowId)
JOIN StRo ON (StRzImRo.Rohstoff = StRo.IntRowId)
WHERE StAt.IntRowId > 0
GROUP BY StRzImRo.Rohstoff, StRo.Bezeichnung
-- GROUP BY StRzImRo.Rohstoff, StRzImRo.Menge, StAt.PROD__REZEPTURGEWICHT, Coalesce(StRz.PARM__BEZUGSGROESSE,1)
The code is fully funcional and tested in IBSQL but not working in my java-application.
My app does work properly with other code. I get this error:
org.firebirdsql.jdbc.FBSQLException: GDS Exception. 335544569. Dynamic SQL Error
SQL error code = -104
Token unknown - line 1, column 266
ON
I would be very happy if someone could help me with this problem. Thanks!
P.S.: Sorry for my bad language, but i´m not a native speaker
The error suggests there is an ON in an unexpected place in your query, and as the query itself looks fine, my guess is the problem is with the way you construct the query in your Java application. There might be some whitespace missing in your query.
My guess is that you have something like
query = "SELECT * " +
"FROM table1" +
"JOIN table2 ON " //.....
The missing whitespace will make the SQL:
SELECT * FROM table1JOIN table2 ON ....
For the parser, this is perfectly valid until it encounters the ON token, which triggers the error. Eg the parser identifies it is a SELECT with * (all) columns from table1JOIN with alias table2. During parsing the server doesn't check if the table actually exists, so it doesn't trip over the fact that table1JOIN doesn't exist. That is checked after parsing is successfully completed.

Using datediff in sql jdbc query

I'm attempting to create a JDBC query with the following statement
String query = "SELECT COLUMN1,DATECOLUMN2 FROM tableName +
"where datediff(d,DATECOLUMN2,getdate()) <= 1";
st = conn1.createStatement();
rs = st.executeQuery(query); //receiving error here
I am receiving the following error message
java.sql.SQLException: "d" is not a recognized table hints option. If it is intended as a parameter to a table-valued function or to the CHANGETABLE function, ensure that your database compatibility mode is set to 90.
I'm sure the query isn't recognizing the datediff function for some reason I am not sure why since i was previously using HQL in the same application and retrieving the values.
In an attempt to use an alternative function I used
{fn TIMESTAMPADD( SQL_TSI_DAY, 1, CURRENT_TIMESTAMP)}
but it also failed I later on found that this is only used for Derby Database's
Can someone assist me in using the proper sql function to compare a date with the current date using JDBC
String query = "SELECT COLUMN1,DATECOLUMN2 FROM tableName "+
"where datediff(day,DATECOLUMN2,getdate()) <= 1";
You have a comma before from. Based on the error messages you are running this against SQL server.
String query = "SELECT COLUMN1,DATECOLUMN2 FROM tableName "
+" where datediff(d,DATECOLUMN2,getdate()) <= 1";
The comma after the "d" should be a dot:
where datediff(d.DATECOLUMN2,getdate())
--------------- ^ dot here
The posted snippet doesn't have a closing double quote between tableName and +, but I figure that is just a typo. However, in your real code, where precisely is the double quote? Is it directly after tablename, like this
String query = "SELECT COLUMN1,DATECOLUMN2 FROM tableName" +
or after the space that follows tablename, like this
String query = "SELECT COLUMN1,DATECOLUMN2 FROM tableName "+
It is very likely the former, because in that case the resulting query would look exactly the way as to cause the error you are getting. Take a look at this:
SELECT COLUMN1,DATECOLUMN2 FROM tableNamewhere datediff(d,DATECOLUMN2,getdate()) <= 1
You can see that where merges with the table name and datediff becomes an alias. What follows is interpreted as table hints. (You can specify table hints without WITH in older versions of SQL Server/older compatibility levels.) Consequently, SQL Server stumbles over d, as that is indeed an incorrect table hint.

Categories