Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/384.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
Java 使用单向或双向关系的不同行为_Java_Hibernate_Jpa_Orm_Eclipselink - Fatal编程技术网

Java 使用单向或双向关系的不同行为

Java 使用单向或双向关系的不同行为,java,hibernate,jpa,orm,eclipselink,Java,Hibernate,Jpa,Orm,Eclipselink,我想持久化一个具有一些资源(内联或附件)的邮件实体。首先,我将它们作为双向关系进行关联: @Entity public class Mail extends BaseEntity { @OneToMany(mappedBy = "mail", cascade = CascadeType.ALL, orphanRemoval = true) private List<MailResource> resource; private String receive

我想持久化一个具有一些资源(内联或附件)的邮件实体。首先,我将它们作为双向关系进行关联:

@Entity
public class Mail extends BaseEntity {

    @OneToMany(mappedBy = "mail", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<MailResource> resource;

    private String receiver;
    private String subject;
    private String body;

    @Temporal(TemporalType.TIMESTAMP)
    private Date queued;

    @Temporal(TemporalType.TIMESTAMP)
    private Date sent;

    public Mail(String receiver, String subject, String body) {
        this.receiver = receiver;
        this.subject = subject;
        this.body = body;
        this.queued = new Date();
        this.resource = new ArrayList<>();
    }

    public void addResource(String name, MailResourceType type, byte[] content) {
        resource.add(new MailResource(this, name, type, content));
    }

}

@Entity
public class MailResource extends BaseEntity {

    @ManyToOne(optional = false)
    private Mail mail;

    private String name;
    private MailResourceType type;
    private byte[] content;
}
执行了三次插入:

INSERT INTO MAIL (ID, BODY, QUEUED, RECEIVER, SENT, SUBJECT) VALUES (?, ?, ?, ?, ?, ?)
INSERT INTO MAILRESOURCE (ID, CONTENT, NAME, TYPE, MAIL_ID) VALUES (?, ?, ?, ?, ?)
INSERT INTO MAILRESOURCE (ID, CONTENT, NAME, TYPE, MAIL_ID) VALUES (?, ?, ?, ?, ?)
然后我想最好只使用一对夫妻的关系。无需保存每个邮件资源中的邮件:

@Entity
public class Mail extends BaseEntity {

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "mail_id")
    private List<MailResource> resource;

    ...

    public void addResource(String name, MailResourceType type, byte[] content) {
        resource.add(new MailResource(name, type, content));
    }

}

@Entity
public class MailResource extends BaseEntity {
    private String name;
    private MailResourceType type;
    private byte[] content;
}
为什么这两次更新?我使用的是EclipseLink,使用另一个JPA提供商作为Hibernate时,这种行为会相同吗?哪种解决方案更好

更新:
-如果我不使用@JoinColumn EclipseLink,它将创建三个表:MAIL、MAILRESOURCE和MAIL\u MAILRESOURCE。我认为这是完全合乎逻辑的。但在@JoinColumn中,它有足够的信息只创建两个表,并且在我看来,只执行插入操作,而不进行更新。

通过定义关系的拥有方来映射,因此对于JPA来说,它提供了更好的方法来处理关联。联接列仅定义关系列。由于JPA是完全基于反射的框架,我可以想到为Mapped所做的优化,因为这样很容易找到拥有方。

当您在OneToMany中使用@JoinColumn时,您定义的是“单向”一对多,这是JPA 2.0中添加的一种新型映射,JPA 1.0不支持这种映射

这通常不是定义OneToMany的最佳方式,普通OneToMany是使用mappedBy并在目标对象中具有多个One来定义的。否则,目标对象不知道该外键,因此需要对其进行单独的更新

您还可以使用JoinTable而不是JoinColumn(这是OneToMany的默认设置),这样目标中就没有外键了

还有第四种选择。您可以将MailResource标记为可嵌入的,而不是实体,并使用ElementCollection

看,,

您是否建议使用OneToMany的mappedBy属性而不是JoinColumn注释?但我只希望生成两个表(Mail和MailResource)。如果我使用可嵌入元素集合,我会得到三个,不是吗?
@Entity
public class Mail extends BaseEntity {

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "mail_id")
    private List<MailResource> resource;

    ...

    public void addResource(String name, MailResourceType type, byte[] content) {
        resource.add(new MailResource(name, type, content));
    }

}

@Entity
public class MailResource extends BaseEntity {
    private String name;
    private MailResourceType type;
    private byte[] content;
}
INSERT INTO MAIL (ID, BODY, QUEUED, RECEIVER, SENT, SUBJECT) VALUES (?, ?, ?, ?, ?, ?)
INSERT INTO MAILRESOURCE (ID, CONTENT, NAME, TYPE) VALUES (?, ?, ?, ?)
INSERT INTO MAILRESOURCE (ID, CONTENT, NAME, TYPE) VALUES (?, ?, ?, ?)
UPDATE MAILRESOURCE SET mail_id = ? WHERE (ID = ?)
UPDATE MAILRESOURCE SET mail_id = ? WHERE (ID = ?)