JPA update list of one to many relationship

2019-04-13 01:01发布

问题:

I have a Question entity with a list of another entity called Alternatives like this:

public class Question {
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "question", cascade = CascadeType.ALL)
    @JsonManagedReference
    private List<Alternative> alternativeList;
}

public class Alternative implements Serializable {
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "questionId", nullable = false)
    @JsonBackReference
    private Question question;

}

Then I wanted to update an exiting Question entry with a new set of Alternative list. For this I'm calling merge method of my JpaDao element with the new Question object:

@Repository
public class JpaQuestionDao implements QuestionDao {
    @PersistenceContext
    private EntityManager em;

    @Transactional
    public Question update(Question question) {
        return em.merge(question);
    }
}

However, this is in fact merging the two lists: the one already in database and the new provided one. I haven't had any problem with such method when I have non-list objects, that's why I kept using merge method.

Is there an alternative method to not merge but only update a list?

回答1:

Retrieve the question object first using EntityManager.find(). Question object will become managed as a result. Since alternativeList is lazily loaded, you have to invoke a method on the collections object to fetch it and make it managed as well. Any updates to the Question object and to the list will be automatically sent to the DB.

@Transactional
public Question update(Question question) {
    Question q = em.find(Question.class, question.getId());
    q.setAlternativeList(null);
    q.setAlternativeList(question.getAlternativeList());
    ...

    return q;
}

Alternatively, you can try using orphanRemoval=true on your @OneToMany collection

@OneToMany(fetch = FetchType.LAZY, mappedBy = "question", cascade = CascadeType.ALL, orphanRemoval=true)
@JsonManagedReference
private List<Alternative> alternativeList;