我有以下问题:
Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction
以及:
Caused by: java.util.ConcurrentModificationException: null
我知道问题出在哪里了。
我尝试更新子实体,即与父实体的关系。当我更新孩子时,刷新效果不好。如果我换了父母,孩子也会留下。这不好。所以,我尝试获取“旧”父对象,从列表中删除子对象,然后继续更新。但是当我移除子对象时,它触发了@preremove注解。我不想那样。
孩子来了:
@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);
}
}
服务(@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);
}
....
}
你知道吗?
编辑1:
删除作业:
public Project removeJob(Job job) {
this.jobs.remove(job);
job.setProject(null);
return this;
}
编辑2:
项目:
@OneToMany(mappedBy = "project", cascade = CascadeType.ALL, orphanRemoval = true)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private Set<Job> jobs = new HashSet<>();
1条答案
按热度按时间rslzwgfq1#
正如jpa-@preremove method behavior中所解释的,@preremove是由孤立作业的删除触发的。
您正确地同步了projet作业双向关联的两端,也许您应该避免使用
@PreRemove
执行其他双向关联同步,而不是在add*
以及remove*
方法,而不是其他地方。你不需要打电话
repository.save
经常这样。在事务性方法中,对托管实体的更改将自动传播,因此您应该只在非托管实体上使用它(这里,对于job
由mapstruct创建)。如果你真的需要冲水,你可以用repository.saveAndFlush
方法,但乍一看没必要。顺便说一下,您保留了jhipster生成的代码,该代码使用相同的代码创建和更新实体
save
方法,它合并了从dto到。我建议使用单独的create和update方法来避免不必要的更新。您还可以利用mapstruct进行更新:https://mapstruct.org/documentation/stable/reference/html/#updating-bean示例希望这有帮助!