following situation. I have three classes (CV=Curriculum Vitae, ProfessionalExperience and Industry). My REST Controller receives a PUT request for updating an existing CV. JSON looks something like this:
{
"id": 102,
"currentSalery":100,
"desiredSalery":120,
"professionalExperiences": [
{ "jobTitle" : "Technical Project Lead", "company" : "Example Company 1",
"monthStart" : 10, "yearStart" : 2008, "monthEnd" : 11, "yearEnd" : 2017, "industry" : {"id" : 1001, "name" : "IT"}
},
{ "jobTitle" : "Software Consultant", "company" : "Example Company 2",
"monthStart" : 11, "yearStart" : 2017, "industry" : {"name" : "Sales"}
}
]}
The relationships between CV and ProfessionalExperience is 1:n. The relationship between ProfessionalExperience and Industry is n:1. Note that the JSON can have already existing Industry Objects as references (here IT) or new ones (here Sales).
Here (I hope) all important parts of the ProfessionalExperience and Industry class
ProfessionalExperience:
@Entity
public class ProfessionalExperience implements Serializable {
@Id
@SequenceGenerator(name="prof_seq", initialValue=1, allocationSize=100)
@GeneratedValue(strategy= GenerationType.SEQUENCE, generator="prof_seq")
private Long id;
@ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
@JoinColumn(name = "industry_id")
private Industry industry;
@JsonIgnore
@ManyToOne
@JoinColumn(name = "cv_id")
private CV cv;
public Industry getIndustry() {
return industry;
}
/**
* Set new industry. The method keeps relationships consistency
* * this professionalExperience is removed from the previous industry
* * this professionalExperience is added to next industry
*
* @param industry
*/
public void setIndustry(Industry industry) {
//prevent endless loop
if (sameAsFormer(industry))
return ;
//set new industry
Industry oldIndustry = this.industry;
this.industry = industry;
//remove from the industry
if (oldIndustry!=null)
oldIndustry.removeProfessionalExperience(this);
//set myself into industry
if (industry!=null)
industry.addProfessionalExperience(this);
}
private boolean sameAsFormer(Industry newIndustry) {
return industry==null? newIndustry == null : industry.equals(newIndustry);
}
}
I implemented the setter as mentioned in JPA/Hibernate: detached entity passed to persist but with no success.
Industry:
@Entity
public class Industry implements Serializable {
@Id
@SequenceGenerator(name="industry_seq", initialValue=1, allocationSize=100)
@GeneratedValue(strategy= GenerationType.SEQUENCE, generator="industry_seq")
private Long id;
// REMOVED cascade = CascadeType.ALL for testing
@JsonIgnore
@OneToMany(mappedBy = "industry")
private List<ProfessionalExperience> professionalExperiences = new ArrayList<>();
/**
* Returns a collection with owned professional experiences. The
* returned collection is a defensive copy.
*
* @return a collection with owned professional experiences
*/
public List<ProfessionalExperience> getProfessionalExperiences() {
return new ArrayList<ProfessionalExperience>(professionalExperiences);
}
/**
* Add new professionalExperience to the industry. The method keeps
* relationships consistency:
*/
public void addProfessionalExperience(ProfessionalExperience professionalExperience) {
// prevent endless loop
if(professionalExperiences.contains(professionalExperience))
return;
professionalExperiences.add(professionalExperience);
professionalExperience.setIndustry(this);
}
/**
* Removes the professionalExperience from the industry. The method keeps
* relationships consistency:
*/
public void removeProfessionalExperience (ProfessionalExperience professionalExperience) {
// prevent endless loop
if(!professionalExperiences.contains(professionalExperience))
return;
professionalExperiences.remove(professionalExperience);
professionalExperience.setIndustry(null);
} }
I played around with different combinations of CascadeTypes on ProfessionalExperience an Industry side, but never got the right combination. If i remove the CascadeType from Industry I just get
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: x.y.z.Industry
With CascadeType.ALL on both sides it depends on the Industry objects I want to save. If there are all new (or no duplicates), then it is working. But if two ProfessionalExperiences are referencing the same Industry object i get this:
Caused by: java.lang.IllegalStateException: Multiple representations of the same entity [x.y.z.Industry#303] are being merged
Can someone help me out? Thans in advance!