Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Jpa 为什么我不能修改实体而不保留其属性?_Jpa - Fatal编程技术网

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.

我创建了一个名为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.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();