JPA: вопрос о слиянии объекта перед его удалением

Я знаю, что перед удалением объекта мне нужно объединить его, но я никогда не думал, что мне придется делать это внутри EJB. Сначала у меня такие:

e = (Event) scholarBean.merge(e);
scholarBean.remove(e);

в моем управляемом компоненте. Это дает мне эту ошибку

java.lang.IllegalArgumentException: Entity must be managed to call remove: com.scholar.entity.Event@998, try merging the detached and try the remove again.

Затем я вношу эти две строки в свой сессионный компонент, и это работает. Есть идеи, почему?

Managed Bean

myEJB.deleteEvent(e);

а также

myEJB.java

public void deleteEvent(Event e){
    e = (Event) merge(e);
    em.remove(e);
}

person Thang Pham    schedule 06.10.2010    source источник


Ответы (3)


Я знаю, что мне нужно объединить объект перед его удалением

Не совсем. Объект, передаваемый для удаления, должен быть сущностью и не должен быть отсоединен. Это другое.

но я никогда не думал, что мне придется делать это внутри EJB. Сначала у меня есть эти (...)

Давайте посмотрим, что вы делаете:

1: e = (Event) scholarBean.merge(e); 
2: scholarBean.remove(e);

Таким образом, в 1: вы вызываете EJB (скорее всего, с Persistence Context на уровне транзакции), который объединяет сущность. Но затем метод завершается, транзакция фиксируется, контекст сохраняемости закрывается, возвращаемый объект снова становится отсоединенным.

А в 2: вы передаете (все еще) отсоединенный объект EJB и пытаетесь remove его remove, что не разрешено. И КаБУМ!

Затем я вношу эти две строки в свой сессионный компонент, и это работает. Есть идеи, почему?

Это работает, потому что теперь вы работаете в рамках контекста постоянства, связанного с транзакцией JTA, и, таким образом, вы действительно передаете управляемый объект в remove.

person Pascal Thivent    schedule 06.10.2010
comment
Замечательный ответ. Большое спасибо - person Thang Pham; 07.10.2010

...и вы даже можете комбинировать их:

Вот так:

    public void deleteManCheck(ManCheck manCheck) {
    em.remove(em.merge(manCheck));
}
person jos de jong    schedule 30.03.2012

У меня были те же проблемы с транзакциями, когда это использовалось в сервлете. При использовании EJB-service-bean из MDB все работало нормально, поскольку транзакция была запущена до вызова EJB, но когда EJB-вызов пришел из сервлета, запущенной транзакции не было. Я решил это в своем веб-приложении, создав фильтр, который запускает и передает UserTransaction. Затем каждый вызов EJB-методов присоединяется к моей UserTransaction вместо того, чтобы начинать собственную транзакцию.

person Frode Halvorsen    schedule 30.07.2012