How to update cascade in JPA

I was stuck trying to cascade the ManyToMany event . I’m bean looking at similar entries, but don’t see where my code is going wrong compared to other posts.

I have two tables Organization and Project , Organization is the owner of the relationship, and there is a relationship table between them.

I am trying to save a new project object that may have one or more organizations associated with it. I am using selectManyListbox (JSF 2) so that a user can select more than one organization. All this works fine until I try to cascade the relationship. Either the project is saved, or the permanent manager creates new copies of the same project for each organization that is associated with it. That is, different orgID and projID (instead of another orgID refer to the same projID)

Why does the JPA create a new instance of the same project (identical properties except ID) when I try to maintain the relationship?

I am trying to learn JPA / JSF and any help is greatly appreciated. Greetings to Chris.

PS. In the Project bean controller, I got the correct instances of the organizations that the user selects.

Primary Key Entity Objects

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

Project bean controller

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

Finally, the facade editing function of Organizationia

@Override
    public void edit(Organisation entity) {
        getEntityManager().merge(entity);
    }
+3
source share
1 answer

I solved the problem and sent a repeat to other users who may make the same mistake as me. Hope all is well.

The problem was creating the bean project function. Before merging (updating) objects of the organization, I had to first call the project (persist) in the project.

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) {

Also, I had a mistake in the method of creating the facade of the project, which was called merge, not persist. Which causes most of the problem. Sorry for taking the place for such a trivial decision.

+3
source

Source: https://habr.com/ru/post/1796207/


All Articles