views:

461

answers:

2

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);
+1  A: 

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.

Bozho
GroupUser doesn't have any cascadable entries.Its strange that I am not able to rely on the cascade=DELETE option as per JPA spec, since the underlying ORM provider deletes all GroupUser instances 1-by-1.This implies that I have to write custom code to optimize deletion of entries.
Samuel
+1  A: 

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

Shervin
Its strange that I am not able to rely on the cascade=DELETE option as per JPA spec, since it deletes all GroupUser instances 1-by-1.This implies that I have to write custom code to optimize deletion of entries.
Samuel
@Samuel. I did ask a very similar question the other day. You can find it here: http://stackoverflow.com/questions/2856460/hibernate-doesnt-generate-cascadeAnd the tip to use @OnDelete instead of cascade could perhaps mean that it doesn't delete instances 1 by 1. You could give it a try. I haven't tried it yet though.
Shervin
@Shervin - @OnDelete works like a charm, somehow missed using it. I would suggest you add support for this also for all @OneToMany annotations.
Samuel
@Samuel. Will do thanks :-)
Shervin
@Saumel: Did you remove the cascading in the `@OneToMany` so that it looks something like this: `@OneToMany @OnDelete(action = OnDeleteAction.CASCADE)`
Shervin
Didn't make any changes to @OneToMany just added the above line for the @OneDelete annotation to get this working.
Samuel