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);
По какой-то причине, независимо от того, есть ли в комиссии скобки или нет, мне нужно:
- Снять скобки с существующей комиссии
- Сохранить
- Удалить существующую комиссию
- Сохранить
- Сохранять новую комиссию
- Установить новую комиссию на досье
- Сохранить
Пропуск любого из шагов вызывает эту ошибку:
На коллекцию с 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);