EclipseLink: проблемы с каскадным удалением при обновлении - PullRequest
5 голосов
/ 03 апреля 2012

Oracle с использованием EclipseLink:

У меня отношения один-ко-многим между родителем (рабочий процесс) и детьми (этап). В базе данных у меня есть ограничение удаления, которое удаляет на этапе удаления рабочего процесса. Это прекрасно работает с sqlplus.

class Workflow {
    @Override
    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "workflow",      targetEntity = Stage.class)
    @JoinColumn(name = "WORKFLOW_ID")
    public Set<Stage> getStages() {
        return m_stages;
    }
}

class Stage {
    @Override
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, optional = false, targetEntity = Workflow.class)
    @JoinColumn(name = "WORKFLOW_ID", nullable = false)
    public Workflow getWorkflow() {
        return m_workflow;
    }
}

когда я загружаю рабочий процесс по имени внутри метода @Transactional (распространение = Propagation.REQUIRED), а затем em.remove (рабочий процесс) этого объекта,

Я получаю исключения, такие как

Error Code: 1407
Call: UPDATE STAGES SET WORKFLOW_ID = ?, FAILURE_STAGE_ID = ?, SUCCESS_STAGE_ID = ? WHERE (STAGE_ID = ?)
bind => [4 parameters bound]

Caused by: java.sql.SQLException: ORA-01407: cannot update    ("DB"."STAGES"."WORKFLOW_ID") to NULL

потому что я определил столбец stage.workflow_id, чтобы он не обнулялся.

Почему eclipselink пытается обновить таблицу этапов с нулевыми идентификаторами рабочего процесса, а не просто удалить саму строку этапа?

Как мне это исправить?

Ответы [ 2 ]

1 голос
/ 18 апреля 2012

У вас не должно быть JoinColumn на WorkFlow, поскольку вы используете mappedBy, что, скорее всего, является причиной.JoinColumn обычно не следует использовать в OneToMany (было разрешено только в JPA 2.0), это только для однонаправленных OneToManys.

В противном случае включите полные классы и трассировку SQL транзакции.Похоже, что он сталкивается с двунаправленным ограничением и пытается разрешить его путем поверхностного удаления.У вас есть другие отношения между ними?

Если вы используете каскадное удаление в базе данных, вы можете пометить отношение OneToMany с @CascadeOnDelete, чтобы избежать оператора удаления.

См., http://wiki.eclipse.org/EclipseLink/Examples/JPA/DeleteCascade

0 голосов
/ 03 апреля 2012

Вы удаляете рабочий процесс, свойство аннотации mappedBy означает, что этапы владеют их рабочим процессом, поэтому реализация JPA обновляет этапы, чтобы привести их в соответствие с тем, как вы отображали эти объекты.

Я предполагаю, что вы хотите удалить mappedBy в Workflow.

Изменение отображений на этапах как это:

class Stage {
    @Override
    @ManyToOne(mappedBy="stages") // supposed to be the name (in Workflow) of the persisted property here, I'm not used to annotate on the getter
    // no JoinColumn - WorkFlow has already defined the relationship
    public Workflow getWorkflow() {
        return m_workflow;
    }
}

На старых этапах (помимо того, что они не работали) вы удалили бы рабочий процесс и, следовательно, удалили все другие этапы в этом рабочем процессе, если вы удалили отдельные этапы. Не думай, что это было реальное намерение.

...