使用JPA编辑Exam实体无效果求助:修改questions属性失效
JPA修改Exam实体的List属性无效果的原因及解决办法
兄弟,你这段代码没生效的核心问题是实体状态的管理错误,咱们一步步拆解:
主要原因
- 你通过
getExam(e.getIdExam())获取的ex实体处于游离状态(Detached)——这个实体不在你后续创建的EntityManager上下文里,JPA的EntityManager只会跟踪「托管状态(Managed)」的实体变化,游离实体的修改它根本“看不见”,所以commit的时候自然不会同步到数据库。 - 你既没有把游离的
ex合并到当前EntityManager的上下文,也没有用当前EntityManager去加载实体,导致修改操作完全脱离了JPA的持久化跟踪机制。
修正方案
方案一:直接在当前EntityManager中加载实体(推荐)
把实体获取逻辑放到当前EntityManager的上下文里,这样拿到的ex就是托管状态,修改后会自动被跟踪:
public void editExam(Exam e) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("QuizPU"); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); // 用当前em查询实体,此时ex处于托管状态 Exam ex = em.find(Exam.class, e.getIdExam()); ex.setQuestions(e.getQuestions()); // 托管实体的修改会在commit时自动同步到数据库 em.getTransaction().commit(); em.close(); emf.close(); }
方案二:合并游离实体到当前上下文
如果必须保留getExam的逻辑,那就用em.merge()把游离实体转为托管状态,再基于返回的托管实体做修改:
public void editExam(Exam e) { Exam ex = getExam(e.getIdExam()); EntityManagerFactory emf = Persistence.createEntityManagerFactory("QuizPU"); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); // merge方法返回托管状态的实体,一定要用这个返回值来做修改 Exam managedEx = em.merge(ex); managedEx.setQuestions(e.getQuestions()); em.getTransaction().commit(); em.close(); emf.close(); }
额外注意点
如果questions是关联的Question实体集合,还要检查Exam类中@OneToMany注解的cascade属性——如果需要同步集合中Question实体的新增/修改/删除,要把cascade设置为CascadeType.ALL或者具体的CascadeType.MERGE/CascadeType.PERSIST,否则只修改集合本身可能不会同步子实体的状态到数据库。
内容的提问来源于stack exchange,提问作者Bashir
相关产品推荐
相关产品推荐

