How to delete a ManyToMany item using JPQL? - java

I have two models, say :
BlogPost(title, message)
Tags(name)
Both have a ManyToMany relationship defined.
Using JPQL, I delete a list of BlogPost with this query:
DELETE FROM BlogPost b WHERE b IN :list
(:list is a List from a previous SELECT requet).
Doing so, I have a ConstraintViolationException because of the relation between BlogPost and Tags.
Is there a way to delete the relation without deleting the Tags using JPQL?
Thanks for your help!

You have to remove the association first, before you delete the entity.

JPA create a table BlogPost_Tags which stores ID of BlogPost and Tags.
So when you try to delete a BlogPost, the constraint on the BlogPost_Tags failed.
You need to delete the relation before delete the Post, and there is no easy way in JPQL, you have to use the EntityManager.

I'll answer myself with the solution I came up. I'm not sure it's the best one, but at least, it works.
Since you want to bulk delete something that have a ManyToMany related items, you first have to delete the relation (in the join table), or do a loop and for each item, delete manually (insane and too much heavy).
So, since JPQL does not allow to do it, a possible way is to make a native SQL query for deleting the id you want in the related table, and then, do the bulk delete.

Related

Hibernate NonUniqueObjectException

I'm getting NonUniqueObjectException in hibernate.
There is one Item class, I saved list of Item objects using session.save of hibernate.
Now in the same transaction, I'm trying to update same Items using raw sql query which has join with another table. This gives me NonUniqueObjectException. The two tables I'm joining are unrelated as entities for hibernate, that is, there is no foreign key relation.
So I have 2 questions:
First, is there any way of using hql for writing inner join queries in hibernate.
Second, how to avoid NonUniqueObjectException.
One of the things that is working is that I clear the session before making any raw sql query. Any better approach is welcomed.

JDBI how can I delete data from two tables in one #SqlUpdate

I have two tables:
entities:
- id
- someValues
and other table, with foregin key on id field
connectedEntities:
- entityId (foregin)
- otherObjectId (foregin)
I need to delete entity by id, but when I tried to delete just from entities table, there's FK violation.
Also, I want to use #SqlUpdate or other annotation from JDBI framework.
Does anybody know how to do something like this?
Thanks to #G_H , I found what I was looking for.
I just needed to add ON DELETE CASCADE to my foregin key definition, and everything worked just fine.
Here's the tutorial - mysqltutorial.org/mysql-on-delete-cascade

How to efficently truncate a many-to-many table in JPA?

I have a JPA many to many relation.
The easiest way of deleting all entries of this relation is doing a findAll(), clearing the collection of the assoziation and flushing the session.
In my case this means loading ~1'000'000 instances into ram just to delete them all. That's not really efficient.
I could resort to SQL and simply truncate the join table. Is there an efficient way to do this in JPA?
You would need to map your m-m table as an additional entity and delete it with a delete statement. If the table is not mapped to an entity, it cannot be deleted by a delete statement. If you just want to delete the m-m relations, this should be enough. If you also wnat to delete related entities, you should map them to the new m-m entity and mark the relationship with cascade on delete.

How to dynamically delete the rows of a table, or delete a table, with Hibernate?

I have a table in an Oracle database.
I want to know how to delete its rows, or how to delete purely the table using Hibernate, but not by changing the corresponding mapped class. I mean, I want to do it ouside the mapped class, in a main Java method for example.
To read data, I always use native SQL queries with Hibernate.
To write data, I use session.save
But how do I do to delete data from a table, or delete the table ?
I looked at the Hibernate documentation, but the solution always involves changing the mapped class code by adding annotations...
I want a solution like the one I use to read and write data :
session.createSQLQuery("...");
Or
session.save(...);
Is there a solution like that ?
I found the answer in another Stackoverflow question :
Query to delete all rows in a table hibernate
If the table from which I want to delete the rows is named MyTable then, the answer is :
in HQL :
session.createQuery("delete from MyTable").executeUpdate();
in native SQL :
session.createSQLQuery("delete from MyTable").executeUpdate();
I should have looked longer in stackoverflow before posting this question, sorry for that.
HQL delete from Xyz will help, as without where clause it will affect every row:
EntityManager em = // .. get EntityManager
em.getTransaction().begin();
em.createQuery("delete from MyTable").executeUpdate();
em.getTransaction().commit();

Hibernate; HQL; why does the delete query not work, but select does?

I want to delete certain records from a table. These records have some child-records in other tables.
In order to be able to delete the main records, I have to delete the child records first.
Here is the example of the HQL used:
delete from ItineraryBooking ib where ib.booking.user.id = :paramId
Basically, this should remove all ItineraryBookings (records in seperate table), these are joined to the Booking table. A Booking table can be joined with the User table.
The odd thing is that when you change the above to:
from ItineraryBooking ib where ib.booking.user.id = :paramId
And execute a Query.list(), it will work just fine.
Whenever I want to execute the delete variant, it looks like Hibernate generates an odd delete statement. Is my HQL wrong? Or is it a Hibernate quirk?
From the hibernate manual:
No joins, either implicit or explicit,
can be specified in a bulk HQL query.
Sub-queries can be used in the
where-clause, where the subqueries
themselves may contain joins.
Your ib.booking.user.id clause looks like a join to me. I don't know if Hibernate actively rejects joins in a delete statement, or just silently gets it wrong.
A nicer way to delete child records is to use cascading deletes.
Simple questions that may help:
Just for curiosity, are you running this HQL in a transaction? selects doesn't need a transaction, but deletes does need it.
Are you flushing the session after executing the deletion HQL?
Are you deleting, and selecting in the same transaction or in separate ones?

Categories