【问题标题】:hibernate EventListener and stackoverflow error休眠EventListener和stackoverflow错误
【发布时间】:2013-10-28 16:15:00
【问题描述】:

我最近遇到了一种情况,当通过 Hibernate 会话删除对象时,我必须执行一些操作。

我不想在删除实体之前删除 unidirectionl relashonship,但以下代码会导致 * 异常。

@Component("emsPreListener")
public class IntegrationEntityDeleteListener implements PreDeleteEventListener {

    private static final long serialVersionUID = 2245534615822054792L;

    @Override
    @SuppressWarnings("unchecked")
    public boolean onPreDelete(PreDeleteEvent event) {

        System.out.println("PRE-DELETE");

        Session session = event.getSession();

        if (event.getEntity() instanceof Project) {
            Transaction transaction = null;
            try
            {
                transaction = session.beginTransaction();

                Project project = (Project) event.getEntity();

                Criteria criteria = session.createCriteria(ProjectPoll.class);
                criteria.add(Restrictions.eq("project", project));
                List<ProjectPoll> polls = criteria.list();
                if(polls != null) {
                    for(ProjectPoll projectPoll : polls) {
                        session.delete(projectPoll);
                    }

                    return false;
                }
            }
            catch (Exception exception) {
                exception.printStackTrace();
            }
            finally
            {
                if(transaction != null) transaction.commit();
            }

        }

        return false;
    }

}

这是唯一具有相关性的实体。

@Entity
@Table(name = "project_poll")
@PrimaryKeyJoinColumn(name = "poll_id", referencedColumnName = "id")
public class ProjectPoll extends Poll {
    private static final long serialVersionUID = -2230614967405436988L;

    @ManyToOne(cascade=CascadeType.ALL)
    @JoinColumn(name = "project_id")
    private Project project;

    public Project getProject() {
        return project;
    }

    public void setProject(Project project) {
        this.project = project;
    }
}

Tnx

【问题讨论】:

  • 每个项目有多少 ProjectPoll 记录?
  • 每个项目可能存在很多 ProjectPoll。

标签: java hibernate


【解决方案1】:

您使用 cascade=CascadeType.ALL 注释了双向关系 ProjectPoll.project。删除 projectPoll 也会删除一个父项(项目)。这又将再次触发 onPreDelete()。尝试删除双向关系的级联属性。

【讨论】:

  • 实体之间的关系不是双向的。架构被设计为尽可能模块化,项目位于核心模块中,无法修改。实际上,我使用 ProjectService 的自定义实现解决了上述问题,但我仍然想知道为什么 Listener 不起作用。
  • 如果我理解正确,一个项目可能会分配给多个 ProjectPoll。在这种情况下,在 onPreDelete() 中删除 projectPoll 也将通过您的级联定义触发删除 Project!在我不明白的情况下,这将在同一个项目对象的 if() 子句中调用您的行为!结果你得到*错误。
  • 正如我之前所说,删除 cascade=CascadeType.ALL 可能会对您有所帮助。在我不明白的明确定义删除级联是一个冗余,因为项目实例已经被删除。您需要的只是将引用设置为 NULL。尝试 projectPoll.setProject(null) 而不是 session.delete(projectPoll);