Как каскадировать обновление в JPA - PullRequest
3 голосов
/ 04 марта 2011

Я застрял, пытаясь заставить работать ManyToMany каскадное событие.Я просматривал похожие посты, но не вижу, где мой код работает неправильно, по сравнению с другими постами.

У меня есть две таблицы Организация и Проект Организация является владельцем отношений, и между ними существует таблица отношений.

Я пытаюсь сохранить новый объект проекта, с которым может быть связана одна или несколько организаций.Я использую selectManyListbox (JSF 2), чтобы позволить пользователю выбрать более одной организации.Все это прекрасно работает, пока я не попытаюсь каскадно связать отношения.Либо только проект становится постоянным, либо постоянный менеджер создает новые копии одного и того же проекта для каждой связанной с ним организации.Т.е. разные orgID и projID (вместо разных orgID ссылаются на один и тот же projID)

Почему JPA создает новый экземпляр того же самого Project (идентичные свойства, кроме идентификатора), когда я пытаюсь сохранить отношение?

Я пытаюсь выучить JPA / JSF, и любая помощь очень приветствуется.Привет Крис.

PS.В контроллере компонента Project я получил нужные экземпляры организаций, которые выбирает пользователь.

Объекты сущностей с первичными ключами

public class Organisation implements Serializable {

private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "idOrganisation")
private Integer idOrganisation;

..

@JoinTable(name = "organisationproject", joinColumns = {
        @JoinColumn(name = "fkOrganisation", referencedColumnName = "idOrganisation")}, inverseJoinColumns = {
        @JoinColumn(name = "fkProject", referencedColumnName = "idProject")})
@ManyToMany (fetch=FetchType.EAGER, cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
private Collection<Project> projectCollection;

..
}

public class Project implements Serializable {

private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "idProject")
private Integer idProject;

..

@ManyToMany(mappedBy = "projectCollection")
    private Collection<Organisation> organisationCollection;
..
}

Контроллер компонента проекта

@ManagedBean (name="projectController")
@SessionScoped
public class ProjectController implements Serializable {

private Project current;
private UISelectMany selectedOrganisations;

...

public String create() {
        UserController userBean = JsfUtil.findBean("userController", UserController.class);
        current.setUser(userBean.getSessionUser());
        current.setTimeStamp(JsfUtil.getTimeStamp());
        try {


            //Use the OrganisationFacade, who is the owner of the relationship and uses Cascade to update the relation
            for(Organisation org : current.getOrganisationCollection()) {
                org.getProjectCollection().add(current);
                ejbOrganisationFacade.edit(org);

            }

            //getFacade().create(current);

            JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/resources/Bundle").getString("ProjectCreated"));
            return prepareCreate();
        } catch (Exception e) {
            JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/resources/Bundle").getString("PersistenceErrorOccured"));
            return null;
        }
    }

public UISelectMany getSelectedOrganisations() {
        return selectedOrganisations;
    }

public void setSelectedOrganisations(UISelectMany selectedOrganisations) {
        this.selectedOrganisations = selectedOrganisations;
    }
...
}

Наконец, функция редактирования фасада Organiasation

@Override
    public void edit(Organisation entity) {
        getEntityManager().merge(entity);
    }

1 Ответ

3 голосов
/ 05 марта 2011

Решил проблему и опубликовал реплей другим, которые могут сделать ту же ошибку, что и я. Надеюсь, что все в порядке.

Проблема была в функции create компонента Project. Перед объединением (обновлением) сущностей организации мне пришлось сначала вызвать create (persist) для проекта.

try {

            getFacade().create(current);

            for(Organisation org : current.getOrganisationCollection()) {
                org.getProjectCollection().add(current);
                ejbOrganisationFacade.edit(org);
            }

            JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/resources/Bundle").getString("ProjectCreated"));
            return prepareCreate();
        } catch (Exception e) {

Также у меня была ошибка в методе create фасада проекта, который вызывал слияние вместо сохранения. Которые вызывают большую часть проблемы. Извините, что заняли место для такого тривиального решения.

...