Different behaviour using unidirectional or bidirectional relation

Posted by sinuhepop on Stack Overflow See other posts from Stack Overflow or by sinuhepop
Published on 2012-03-27T23:27:41Z Indexed on 2012/03/27 23:28 UTC
Read the original article Hit count: 280

Filed under:
|
|
|

I want to persist a mail entity which has some resources (inline or attachment). First I related them as a bidirectional relation:

@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;
}

And when I saved them:

Mail mail = new Mail("[email protected]", "Hi!", "...");
mail.addResource("image", MailResourceType.INLINE, someBytes);
mail.addResource("documentation.pdf", MailResourceType.ATTACHMENT, someOtherBytes);
mailRepository.save(mail);

Three inserts were executed:

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 (?, ?, ?, ?, ?)

Then I thought it would be better using only a OneToMany relation. No need to save which Mail is in every 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;
}

Generated tables are exactly the same (MailResource has a FK to Mail). The problem is the executed 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 = ?)

Why this two updates? I'm using EclipseLink, will this behaviour be the same using another JPA provider as Hibernate? Which solution is better?

© Stack Overflow or respective owner

Related posts about java

Related posts about hibernate