У меня есть следующие две сущности с OneToOne отношения между ними:Упорство OneToOne отношения с SpringData JPA
@Entity
@Table(name = "tasks")
public class Task {
@OneToOne(mappedBy = "task", cascade = CascadeType.PERSIST)
private Tracker tracker;
/* More code */
}
@Entity
@Table(name = "trackers")
public class Tracker {
@OneToOne
@JoinColumn(name = "trk_task", unique = true)
private Task task;
/* More code */
}
Я пытаюсь запустить этот код:
Task task = taskService.findDispatchableTask();
if (task != null) {
Tracker tracker = trackerService.findIdleTracker();
if (tracker != null) {
task.setTracker(tracker);
task.setStatus(TaskStatus.DISPATCHED);
taskService.save(task);
}
}
Но я получаю эту ошибку :
ERROR org.hibernate.AssertionFailure - an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
org.hibernate.AssertionFailure: non-transient entity has a null id
я могу "решить" это изменение моего кода:
Task task = taskService.findDispatchableTask();
if (task != null) {
Tracker tracker = trackerService.findIdleTracker();
if (tracker != null) {
tracker.setTask(task);
trackerService.save(tracker);
task.setTracker(tracker);
task.setStatus(TaskStatus.DISPATCHED);
taskService.save(task);
}
}
Мой вопрос: Каков правильный способ сохранения отношения OneToOne? В моем коде, Почему я сохраняю обе части отношения, чтобы заставить его работать?
Спасибо за отличный ответ. Я понимаю это сейчас, но я не понимаю, почему мне не нужно сохранять свои объекты явно. Что save() делает для вызова метода сохранения репозитория(), который является транзакционным. Что мне делать? –
Пункт транзакции заключается в том, чтобы иметь возможность изменять несколько объектов, из нескольких видов, атомарно. Либо все спасено, либо ничего. Именно это гарантирует согласованность данных. И поэтому сервисы должны быть транзакционными, а не только репозиториями. Как только вы загружаете объекты в транзакцию и изменяете их в одной транзакции, Hibernate автоматически сохраняет изменения, не требуя явно их сохранения. Короче говоря, весь код в вашем вопросе должен быть в методе транзакционной службы, и вам не нужно будет вызывать 'save()'. –