Hibernate несколько сохранений, необходимых для удаления сирот

Рассмотрим следующую модель сущности:

Сущность досье.

@Entity
@Table(name = "dossiers", uniqueConstraints = @UniqueConstraint(columnNames = { "site_id", "dossier_id" }))
@Audited(withModifiedFlag = true)
@Access(AccessType.FIELD)
public final class Dossier extends EntityObject {

    @Column(name = "name", nullable = false, length = 255)
    private String name;

    @OneToOne(fetch = FetchType.EAGER, mappedBy = "dossier", optional = true, cascade = CascadeType.ALL, orphanRemoval = true)
private Commission commission;

}

Субъект комиссий.

@Entity
@Table(name = "commissions")
@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
@Access(AccessType.FIELD)
public class Commission extends EntityObject{

    @Column(name = "name")
    private String name;

    @OneToMany(mappedBy = "commission", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
    @OrderBy(clause = "boundary ASC NULLS LAST")
    private List<CommissionBracket> commissionBrackets;

    @OneToOne(optional = true)
    @JoinColumn(name = "dossier_id", nullable = true)
    private Dossier dossier;

}

Скобка сущность.

@Entity
@Table(name = "commission_brackets")
@Access(AccessType.FIELD)
public class CommissionBracket extends EntityObject {

    @ManyToOne(optional = false)
    @JoinColumn(name = "commission_id")
    private Commission commission;

    @Column(name = "boundary")
    private Integer boundary;
}

Теперь, когда я хочу заменить комиссию из досье. Я должен сделать это:

    boolean notSaved = true;
    if(domain.getCommission() != null) {
        toSave.setCommission(domain.getCommission());
        toSave.getCommission().getCommissionBrackets().clear();
        toSave = dossierRepository.save(toSave);
        toSave.setCommission(null);
        toSave = dossierRepository.save(toSave);
        notSaved = false;
    }
    if(dossier.getCommission() != null) {
        final Commission newCommission = commissionRepository.save(dossier.getCommission());
        toSave.setCommission(newCommission);
        toSave = dossierRepository.save(toSave);
        notSaved = false;
    }
    if(notSaved) {
        toSave = dossierRepository.save(toSave);
    }

Обратите внимание, что операция сохранения в репозитории сохраняется или объединяется в зависимости от того, задан ли переданный объект или нет.

В то время как нормальный человек со здравым смыслом подумал бы, что он мог бы просто сделать:

dossier.setCommission(newCommission);
dossierRepository.save(newCommission);

По какой-то причине, независимо от того, есть ли в комиссии скобки или нет, мне нужно:

  1. Снять скобки с существующей комиссии
  2. Сохранить
  3. Удалить существующую комиссию
  4. Сохранить
  5. Сохранять новую комиссию
  6. Установить новую комиссию на досье
  7. Сохранить

Пропуск любого из шагов вызывает эту ошибку:

На коллекцию с cascade="all-delete-orphan" больше не ссылался экземпляр владельца объекта: Commission.commissionBrackets

Хотя этому может быть правдоподобное объяснение, это кажется очень уродливым, и, может быть, есть более чистый способ сделать это? Вместо того, чтобы удалить существующую комиссию, я мог бы также полностью обновить ее, но это не будет отражать функциональную реальность.

Используемая версия Hibernate: 4.3.10. Используемая конечная база данных: postgres 9.4.4.1.

Итак, мои вопросы. Я делаю это правильно или это где-то улучшается?

1 ответ

Вы не опубликовали все соответствующие данные об объекте, например Commissionотношение к Dossier, но mappedBy говорит, что это там. поскольку Dossier находится в двустороннем отношении к Commission (а также Commission бывает принадлежащей стороной отношения), вам просто нужно поддерживать обе стороны. Это должно работать:

// break the current relation, should cause old commissions object to be deleted
dossier.getCommission().setDossier(null);
newCommission.setDossier(dossier);
dossier.setCommission(newCommission);
dossierRepository.save(dossier);
Другие вопросы по тегам