由以下原因引起:java.util.concurrentmodificationexception:null,带preremove注解

bfhwhh0e  于 2021-06-27  发布在  Java
关注(0)|答案(1)|浏览(494)

我有以下问题:

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<>();
rslzwgfq

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示例
希望这有帮助!

相关问题