Рассмотрим три следующих объекта с соответствующими отношениями:
public class Project {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
protected UUID id;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "project", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Event> events = new HashSet<>();
@OneToMany(fetch = FetchType.LAZY, mappedBy = "project", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Entry> entries = new HashSet<>();
}
public class Event {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
protected UUID id;
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name="project_id")
private Project project;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "event")
protected Set<Entry> entries = new HashSet<>();
}
public class Entry {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
protected UUID id;
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumn(name="project_id")
private Project project;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="event_id", nullable=false)
protected Event event;
}
Теперь у меня есть метод, который получает проект с входными событиями и создает из него записи и дополнительные события.,После этого все они должны быть сохранены.
Основными проблемами, которые я обнаружил, были:
(1) Поскольку Генерация идентификатора находится в базе данных , я не могу добавить их всев проект, а затем сохраните записи.Чтобы синхронизировать двунаправленные отношения, мне нужно сначала сохранить их, а затем добавить или сохранить проект и каскадировать записи после добавления.Особенно, когда у меня есть коллекция сущностей, которые уже сохранены, и сущности, у которых еще нет PK, мне нужно очистить набор всей коллекции новой или сохранить сущности перед их добавлением.
(2) Порядок каскадирования отсутствует : При попытке сохранить проект и каскадировании записей дочерние объекты не могут иметь взаимозависимых отношений.Например, что если он попытается сохранить записи до сохранения событий?Я не смог найти никакой опции для установки каскадного порядка.
(3) Двунаправленное отношение между входом-событием также необходимо синхронизировать,Однако некоторые события добавляются недавно, в то время как другие уже существуют и сохраняются, а для вновь добавленных нам необходимо следить за (1).
Вопрос в том, как это сделать.лучше всего?
Я мог бы сохранять сущности во время создания, но тогда у меня была бы одна транзакция при каждом создании.В качестве альтернативы я мог бы сохранить их все в объекте результата и в конце сохранить их, а затем добавить их в проект и сохранить проект.Тем не менее, оба эти варианта мало используют опцию каскадирования и являются довольно сложными в том смысле, что они добавляют временные зависимости.(сначала сохраните X, затем Y, затем Z) * 1032 *
Обновление: код, как я сейчас добавляю сущности и сохраняю их в проект
В проекте есть вспомогательные методы, которые устанавливают толькоЗаписи (может установить двунаправленное отношение, но Project не может быть нулевым при создании записи / события):
public void addEntries(Collection<Entry> entries){
this.entries.addAll(entries);
}
public void addEvents(Collection<Event> events){
this.events.addAll(events);
}
public void addEntry(Entry entry){
this.entries.add(entry);
}
public void addEvent(Event event){
this.events.add(event);
}
В настоящее время я сохраняю события при создании и записи после функции моделирования.Проект всегда сохраняется в самом конце после всех операций.
public ADEvent createADEvent(Round round) {
ADEvent event = new ADEvent(round);
event = saveDB ? eventRepository.save(event) : event;
round.getProject().addEvent(event);
return event;
}
public void saveEntries(Project project, Collection<Entry> entries) {
if (saveDB) entries = entries.stream().map(entryRepository::save).collect(Collectors.toList());
project.addEntries(entries);
}
public Project saveProject(Project project) {
return saveDB ? projectRepository.save(project) : project;
}
Обновления выполняются таким же образом, просто я очищаю всю коллекцию в проекте перед запуском метода симуляции.(и удалить все события симуляции)