我现在正在使用Hibernate 4.1.1很长一段时间。 下面:我创建了一个EventListener,它由Hibernate的Integrator接口集成。到目前为止,这有效!
我正在尝试删除实体,例如帐户。 帐户与播放列表具有一对多的关系。
我想要实现的目标: 删除帐户时删除播放列表。
我知道我可以通过向Hibernate Mappings添加级联行为来实现这一点。 到目前为止,这将工作,但Hibernate无法提供在级联上设置值null的功能,所以我想手动执行这些步骤:
@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;
}
我正在遇到以下问题:
那我怎么解决呢?
答案 0 :(得分:1)
提交事务上的StackOverflow会发生,因为它再次调用onPreDelete处理程序(并且一次又一次)。为了避免你需要检测(在你的监听器内)你已经处理过这个对象的删除。这可以通过以下方法完成:
private final Collection<Long> processingAccounts =
Collections.newSetFromMap(new ConcurrentHashMap<Long, Boolean>());
...
@Override public boolean onPreDelete(final PreDeleteEvent preDeleteEvent)
throws HibernateException {
....
} else if (preDeleteEvent.getEntity() instanceof AccountEntry) {
// check if it's already been processed
if (processingAccounts.contains(preDeleteEvent.getEntity().getId())
return false;
// block it by ID
processingAccounts.add(preDeleteEvent.getEntity().getId();
try {
....
} finally {
// release
processingAccounts.remove(preDeleteEvent.getEntity().getId()
}
}
return false;
}
当然,您可以通过复合键或实体锁定它(如果它具有哈希码+等于实现)。但这是如何解决它的一般原则。