Could hibernate be causing this 'fetch out of sequence' error? - java

I am attempting to execute this query (in an Oracle DB) with Hibernate/Spring JPA:
#Query( value = "DELETE from MY_TABLE where ID = :ID", nativeQuery = true)
void delete(Long ID);
There is a BEFORE DELETE trigger on the table that is making up for poor table design that I cannot change, it runs around deleting rows from dependent tables so that the base DELETE doesn't cause any foreign key errors. I am fairly sure this shouldn't be an issue, but if it is let me know.
Now then, on execution this query causes a ORA-01002: fetch out of sequence error which, according to google, is caused when a fetch has been attempted from a cursor which is no longer valid. (To be completely clear, I have not initiated any cursors with my query or my trigger)
BUT, the row and all its dependants are actually being deleted successfully. Because of this I am not sure what is causing the error and would like yalls' help

The method should be :
#Modifying
#Query( value = "DELETE from MY_TABLE where ID = :ID", nativeQuery = true)
void delete(#Param("ID") Long ID);
Try this and check if the issue still exists.

Related

How to force Hibernate use AND in update query?

I am trying to update a raw by composite primary key by using hibernate.
Hibernate uses the next style for such updates:
update mytable set mycolumn=321 where (left_pk, right_pk) = (123, 456);
Is it possible to force hibernate to use the next style?:
update mytable set mycolumn=321 where left_pk = 123 and right_pk = 456;
Both queries work but with a huge difference (at least in MariaDB).
If we use repeatable read transaction then the first query locks the whole table for updates and the second query locks only the single row for updates.
I would prefer to lock only a single row, so I need to use the second query.
You can go for NamedQueries approach in Hibernate,
For example:
//Create Query
#NamedQueries({ #NamedQuery(name = " YOUR QUERY NAME",
query = "from DeptEmployee where department = :department and emp = :emp") })
// set multiple parameters
query.setParameter("department",department)
.setParameter("emp", emp)
Try giving this a shot.

Update single column field in table using Hibernate query

I am trying to update the single value in table (without updating any others) by using Hibernate.
Here is my code:
#Override
public void updateUser(User userDetails){
Query query = session.createQuery("UPDATE User u set u.balance = :balanceValue where u.userId = :userIdValue AND c.userType = :userTypeValue");
query.setParameter("balanceValue", userDetails.getBalance());
query.setParameter("userIdValue", userDetails.getUserId());
query.setParameter("userTypeValue", userDetails.getUserType());
query.executeUpdate();
}
Please note that all parameters I am inserting are String. Columns u.userType and u.userId are composite keys.
Caused by: java.sql.SQLException. Incorrect syntax near the keyword
"IN".
I have spent hours on understanding what is wrong with this query. I am using "User" entity for save, update criteria (writing all fields) and delete row without any problems. Thank you in advance for any help.

Java Hibernate : Update most recent entry in MySql database

This is my requirement. I have a bunch of rows with similar data. I want to update some columns on the LATEST entry. So I have written a hibernate query which goes like this
String hql = "UPDATE Studenttable T set T.timestamp=:time,T.Action=:action where T.StudentId=:studentId and T.teacherId=:TeacherId order by T.teacher_student_mapping_id DESC";
Query query = session.createQuery(hql);
query.setParameter("time",time);
query.setParameter("studentId", studentId);
query.setParameter("TeacherId", teacherId);
query.setParameter("action", action);
query.setMaxResults(1);
query.executeUpdate();
What this does is it updates all the rows which satisfies the condition and then returns the latest row. Instead I want it to fetch the latest row satisfying the conditions, and then update it. How can I do it? Any help is deeply appreciated.
P.S. the teacher_student_mapping_id is an auto-generated value, which is also a primary key.
Time is the current time.
Please don't try to make sense of the table, I have changed the names of the columns for confidentiality.
try
String hql = "UPDATE Studenttable T set T.timestamp=:time,T.Action=:action where T.StudentId=:studentId and T.teacherId=:TeacherId order by T.timestamp DESC LIMIT 1";
Since tagged hql you can try something like below. Updating only the latest one based on pk.
UPDATE Studenttable T set T.timestamp=:time,T.Action=:action where T.StudentId=:studentId and T.teacherId=:TeacherId
and T.pk = (select max(tb.pk) from Studenttable tb where tb.StudentId=:studentId and tb.teacherId=:TeacherId )

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

HQL, can I parameterize the FROM clause?

I have this HQL query:
Query q = em.createQuery (
"DELETE FROM Annotation a WHERE a.id IN ( " +
" SELECT ja.id FROM :entityName an JOIN an.annotations ja)"
);
and I'm being told: QuerySyntaxException: unexpected token: : near line 1
Do I have any hope of making the entity name after FROM a parameter? I have a list of entities to send to this query and I'm afraid that string concatenation is too slow.
You can't substitute the Entity name the parameters work for entity properties not instead.
You could select the entities ids to be deleted with one query and then pass them to a second delete query, but for READ_COMMITED transaction isolation you might still end up with someone else inserting one child entity that would have matched your query. SERIALIZABLE will solve this issue.

Categories