Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA entitymanager remove operation is not performant

When I try to do an entityManager.remove(instance) the underlying JPA provider issues a separate delete operation on each of the GroupUser entity. I feel this is not right from a performance perspective, since if a Group has 1000 users there will be 1001 calls issued to delete the entire group and itr groupuser entity.

Would it make more sense to write a named query to remove all entries in groupuser table (e.g. delete from group_user where group_id=?), so I would have to make just 2 calls to delete the group.

@Entity
@Table(name = "tbl_group")

public class Group {

    @OneToMany(mappedBy = "group", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @Cascade(value = DELETE_ORPHAN)
    private Set<GroupUser> groupUsers = new HashSet<GroupUser>(0);
like image 201
Sam Avatar asked May 17 '10 10:05

Sam


People also ask

How do I delete EntityManager?

To delete a record from database, EntityManager interface provides remove() method. The remove() method uses primary key to delete the particular record.

How do you remove entity from persistence context?

You can prevent that by calling the flush method on the EntityManager. After you've done that, you can remove a specific entity from the persistence context by calling the detach method or you can call the clear method to clear the persistence context completely.

What does EntityManager clear do?

Clearing the entity manager empties its associated cache, forcing new database queries to be executed later in the transaction. It's almost never necessary to clear the entity manager when using a transaction-bound entity manager.


2 Answers

Simple answer is yes. If you want to delete a Group and you know there are tons of records in GroupUser table, then it is much better to create a delete query that will do all in one batch instead of one and one.

If you have no cascading on the underlying database, (or even if you do) its good practice to do it in correct order.

So delete the GroupUser first.
Assuming you have a the Group object you want to delete.

int numberDeleted = entityManager.createQuery("DELETE FROM GroupUser gu WHERE gu.group.id=:id").setParameter("id",group.getId()).executeUpdate();

The returning int shows how many records where deleted.

Now you can finally delete Group

entityManager.remove(group);
entityManager.flush();

UPDATE

Seems like @OnDelete on the @OneToMany does the trick

like image 57
Shervin Asgari Avatar answered Sep 18 '22 23:09

Shervin Asgari


Since the GroupUser may have cascades as well, I don't think there is a way to tell hibernate to batch-delete them via configuration.

But if you are certain there are no cascade=DELETE on GroupUser, feel free to issue an HQL/JPA-QL query:

DELETE FROM GroupUser WHERE group=:group

If there are cascades, handle them with a query as well.

like image 33
Bozho Avatar answered Sep 18 '22 23:09

Bozho