Различное поведение с использованием однонаправленного или двунаправленного отношения

Я хочу сохранить почтовый объект, который имеет некоторые ресурсы (встроенные или прикрепленные). Сначала я связал их как двунаправленное отношение:

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

И когда я их сохранил:

Mail mail = new Mail("asdasd@asd.com", "Hi!", "...");
mail.addResource("image", MailResourceType.INLINE, someBytes);
mail.addResource("documentation.pdf", MailResourceType.ATTACHMENT, someOtherBytes);
mailRepository.save(mail);

Было выполнено три вставки:

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

Тогда я подумал, что будет лучше использовать только отношение OneToMany.Не нужно сохранять, какая Почта находится в каждом 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;
}

Сгенерированные таблицы абсолютно одинаковы (у MailResource есть FK для Mail). Проблема заключается в выполнении 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 = ?)

Почему эти два обновления? Я использую EclipseLink, будет ли такое же поведение при использовании другого поставщика JPA в качестве Hibernate? Какое решение лучше?

ОБНОВЛЕНИЕ: - Если я не использую @JoinColumn, EclipseLink создает три таблицы: MAIL, MAILRESOURCE и MAIL_MAILRESOURCE. Я думаю, это совершенно логично. Но с @JoinColumn у него достаточно информации для создания только двух таблиц и, по-моему, только вставки, без обновлений.

6
задан sinuhepop 28 March 2012 в 08:49
поделиться