Jpa 为什么我不能修改实体而不保留其属性?
我创建了一个名为Mail的jpa实体,它有两个外键Jpa 为什么我不能修改实体而不保留其属性?,jpa,Jpa,我创建了一个名为Mail的jpa实体,它有两个外键 public class Mail implements Serializable { @ManyToOne(optional = false, fetch = FetchType.LAZY) @JoinColumn(name = "auteur") private User user; @JoinColumn(name = "typeC") @ManyToOne(optional = false, fetch = FetchType.
public class Mail implements Serializable {
@ManyToOne(optional = false, fetch = FetchType.LAZY)
@JoinColumn(name = "auteur")
private User user;
@JoinColumn(name = "typeC")
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private Type typeMail;
....
当我想修改邮件时,我会这样做:
public void modifyMail(Mail mail) {
Mail m = em.find(Mail.class, mail.getId());
m.setUser(mail.getUser());
m.setType(mail.getType());
em.persist(m);
}
但它不起作用。在glassfich日志中,em.persist工作正常,但glassfich也指示用户表中的插入;在User表中,名称是唯一的,因此它不起作用,我不知道glassfich为什么尝试创建与邮件关联的用户。如果有人知道为什么,他能告诉我吗 实体管理器跟踪从中获得的所有对象/实例。因此,如果使用em.find加载用户,它将了解此用户实例 如果在关闭用于加载用户实例的事务后保留用户实例,则这些实例将过时。实体经理不再真正了解它们,而是假设它们是新的 因此,上述代码需要:
public void modifyMail(Mail mail) {
Mail m = em.find(Mail.class, mail.getId());
User u = em.find(User.class, mail.getUser().getId());
m.setUser(u);
m.setType(mail.getType());
em.persist(m);
}
或
原因是实体管理器不知道用户或邮件的含义。它的所有对象都是相同的。因此,如果在某处更改用户,邮件中的用户实例可能已过时
但更好的方法可能是在邮件实例实际更改时更改代码:
em.getTransaction().begin();
Mail mail = em.find(Mail.class, id);
User u = em.find(User.class, userId);
mail.setUser(u);
em.getTransaction().end();
因此,不要收集更改,而是启动事务,加载EM中涉及的所有对象,进行更改并提交事务。您可以添加EM.persist不需要,因为如果管理对象,则会截获对字段的任何更新。@BillyFrost:真的吗?我从来没有试过这个;我假设我需要提交对对象的更改,我看到的每个示例最终都会调用persist。但你似乎是对的:非常感谢我尝试了Aaron给出的第一个代码,它很有效。
em.getTransaction().begin();
Mail mail = em.find(Mail.class, id);
User u = em.find(User.class, userId);
mail.setUser(u);
em.getTransaction().end();