I’m working with Hibernate 4.1.1 for quite a while now.
Following: I’ve created an EventListener which is integrated by the Integrator Interface of Hibernate. So far, this works!
I’m trying to delete an Entity, for example an Account.
An account has a one to many relation to playlists.
What I want to achieve:
Delete Playlists when Account is deleted.
I know that I can achieve this by adding cascade behavior to my Hibernate Mappings.
So far, this will work, but Hibernate isn’t able to provide functionality to set a value null on cascade, so I wanted to do those steps manually:
@Override public boolean onPreDelete(final PreDeleteEvent preDeleteEvent) throws HibernateException
{
if (preDeleteEvent.getEntity() instanceof PresetEntry) {
} else if (preDeleteEvent.getEntity() instanceof AccountEntry) {
final Session session = this.sessionFactory.getCurrentSession();
if (!session.getTransaction().isActive()) {
session.getTransaction().begin();
}
final AccountEntry accountEntry = (AccountEntry) preDeleteEvent.getEntity();
session.createQuery("DELETE FROM PlaylistEntry WHERE ACCOUNT_ID = " + accountEntry.getIdentity()).executeUpdate(); //NON-NLS
} else if (preDeleteEvent.getEntity() instanceof PlaylistEntry) {
} else if (preDeleteEvent.getEntity() instanceof QueueEntry) {
}
return false;
}
I’m running in following issues:
- A transaction is already open because the account is currently deleted
- Calling commit inside onPreDelete results in StackOverflowError (it’s endlessly committing the delete playlistEntry query)
- If the query isn’t commited inside the onPreDelete method the queries will be executed, however the Swing Application begins to freeze forever.
- Not removing the playlists results in foreign key no action exception
So how can I solve that?
StackOverflow on commiting transaction happens, because it calls onPreDelete handler again (and again and again). In order to avoid that you need to detect (inside your listener) that you already handled removal of this object. This can be done either by a following approach:
Of course, you can lock it by a compound key or by entity (if it has hash-code + equals implemented). But this is the general principle how it can be resolved.