I got stuck trying to make a ManyToMany cascading event to work. I’ve bean browsing through similar posts, but can’t see where my code goes wrong, compared to others posts.
I have two tables Organisation and Project, Organisation is the owner of the relationship and there is a relation table between the two.
I am trying to persist a new project entity, that can have one or more organisation associated to it. I use a selectManyListbox(JSF 2) to let the user choose more than one organisation. All this works fine until I try to cascade the relationship. Either only the project is getting persisted or the persistent manager creates new copies of the same project, for every organisation that is associated to it. I.e. different orgID and projID (instead of different orgID refer to the same projID)
Why does JPA makes new instance of the same Project (identical properties, except the ID) when I try to persist the relation ?
I am trying to learn JPA/JSF and any help is very welcomed. Greetings Chris.
PS. In the Project bean controller I got the right instances of Organisations that the user selects.
Entity objects with primary keys
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 Organiasation facade edit function
@Override
public void edit(Organisation entity) {
getEntityManager().merge(entity);
}
Solved the problem, and posting a replay to others who may do the same error that I did. Hope that is ok.
The problem was in the create function of the Project bean. Before merging (updating) the Organisation entities, I had to call the create (persist) on the project first.
Also I had a error in the create method of the project facade, which called merge instead of persist. Which cause much of the problem. Sorry for taking up space for such a trivial solution.