I have the following issues :
Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction
And:
Caused by: java.util.ConcurrentModificationException: null
I see where is the problem.
I try to update a child entity, relationship ManyToOne with the parent. When I update the child, the refresh wasn't good. If I change the parent, it keeps the child. It isn't good. So, I'm trying to get the "old" parent, remove the child from it's list and then continue the update. But when I remove the child, it trigger's the @Preremove annotation. And I don't want that.
Here's the child:
@Entity
@Table(name = "job", schema = "public")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Job implements Serializable {
...
...
@ManyToOne(cascade = CascadeType.REFRESH,fetch = FetchType.LAZY)
@OnDelete(action = OnDeleteAction.CASCADE)
@JsonIgnoreProperties(value = "jobs", allowSetters = true)
private Project project;
..
...
...
public Project getProject() {
return project;
}
public Job project(Project project) {
this.project = project;
return this;
}
public void setProject(Project project) {
this.project = project;
}
...
...
...
@PreRemove
public void removeAppUsers() {
if(this.appUsers.size()>0)
for (AppUser ap : this.appUsers) {
ap.removeJob(this);
}
if(this.performances.size()>0)
for (Performance p : this.performances) {
p.setJob(null);
}
}
There's the service (@Service, @Transactional):
public JobDTO save(JobDTO jobDTO) {
Optional<Project> projectToRemove;
Project p;
log.debug("Request to save Job : {}", jobDTO);
Job job = jobMapper.toEntity(jobDTO);
projectToRemove=projectRepository.findProjectByJob(jobDTO.getId());
jobRepository.save(job);
if(projectToRemove.isPresent()&&jobDTO.getProjectId()!=projectToRemove.get().getId()) {
projectToRemove.get().removeJob(job);
projectRepository.save(projectToRemove.get());
}
if (jobDTO.getProjectId() != null) {
p = projectRepository.findById(jobDTO.getProjectId()).get();
p.addJob(job);
projectRepository.save(p);
job.setProject(p);
jobRepository.save(job);
}
....
}
Do you have any idea?
EDIT 1:
removeJob:
public Project removeJob(Job job) {
this.jobs.remove(job);
job.setProject(null);
return this;
}
EDIT 2:
Project:
@OneToMany(mappedBy = "project", cascade = CascadeType.ALL, orphanRemoval = true)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private Set<Job> jobs = new HashSet<>();