如何在JPA中级联更新

时间:2011-03-04 05:45:46

标签: java jsf jpa glassfish ejb-3.0

我试图让 ManyToMany 级联事件发挥作用。我浏览类似的帖子,但与其他帖子相比,无法查看我的代码出错的位置。

我有两个表组织项目,组织是关系的所有者,两者之间有一个关系表。

我正在尝试保留一个新项目实体,该实体可以有一个或多个与之关联的组织。我使用 selectManyListbox (JSF 2)让用户选择多个组织。所有这一切都很好,直到我尝试级联关系。对于与其关联的每个组织,要么只保留项目,要么持久管理器为同一项目创建新副本。即不同的orgID和projID(而不是不同的orgID引用相同的projID)

为什么当我尝试保持关系时,JPA会创建相同项目的新实例(除ID之外的相同属性)?

我正在尝试学习JPA / JSF,非常欢迎任何帮助。问候克里斯。

PS。在Project bean控制器中,我得到了用户选择的正确的组织实例。

具有主键的实体对象

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;
..
}

项目bean控制器

@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 个答案:

答案 0 :(得分:3)

解决了问题,并将重播发布给可能会犯同样错误的其他人。希望没关系。

问题出在Project bean的 create 函数中。在合并(更新)组织实体之前,我必须先在项目上调用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 方法中出现错误,该方法称为merge而不是persist。这导致了很多问题。很抱歉为这个简单的解决方案占用空间。