Ich möchte eine Mail-Entität beibehalten, die über einige Ressourcen verfügt (Inline oder Anhang). Zuerst erzählte ich ihnen als bidirektionaler Beziehung:Unterschiedliches Verhalten mit unidirektionaler oder bidirektionaler Beziehung
@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;
}
Und wenn ich sie gerettet:
Mail mail = new Mail("[email protected]", "Hi!", "...");
mail.addResource("image", MailResourceType.INLINE, someBytes);
mail.addResource("documentation.pdf", MailResourceType.ATTACHMENT, someOtherBytes);
mailRepository.save(mail);
Drei Einsätze ausgeführt wurden:
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 (?, ?, ?, ?, ?)
Dann dachte ich, es nur besser verwenden würde eine OneToMany-Beziehung. Keine Notwendigkeit zu sparen, die E-Mail in jedem MailResource ist:
@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;
}
erzeugten Tabellen sind genau die gleichen (MailResource hat einen FK Mail). Das Problem ist das ausgeführte SQL:
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 = ?)
Warum diese zwei Updates? Ich verwende EclipseLink. Ist dieses Verhalten dasselbe, wenn ich einen anderen JPA-Anbieter als Hibernate verwende? Welche Lösung ist besser?
UPDATE: - Wenn ich nicht @JoinColumn Eclipse erstellt drei Tabellen: MAIL, MAILRESOURCE und MAIL_MAILRESOURCE. Ich denke, das ist vollkommen logisch. Aber mit @JoinColumn hat es Informationen genug, um nur zwei Tabellen zu erstellen und meiner Meinung nach nur Inserts, ohne Updates.
Deuten Sie das mappedBy Attribut OneToMany statt JoinColumn Anmerkung zu benutzen? –
Ja. Ich denke, es wird immer besser funktionieren. –