考虑以下三个具有各自关系的实体:
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)由于 ID生成在数据库中,因此我无法将它们全部添加到项目中,然后保存条目。为了使双向关系保持同步,我需要先保存它们,然后添加,或者保存项目并在添加后级联条目。尤其是当我有一个已经保存的实体集合和尚没有PK的实体时,我需要清除整个集合的新设置,或者在添加它们之前保存这些实体。
(2)无级联顺序:在尝试保存项目并级联条目时,子实体不能具有相互依赖的关系。例如。如果尝试在保存事件之前保存条目怎么办?我找不到设置级联顺序的任何选项。
(3)进入事件之间的双向关系也需要保持同步。但是,有些事件是新添加的,而其他事件已经存在并已保存,对于新添加的事件,我们需要注意(1)。
问题是:如何做到最好?
我可以在创建时保存实体,但是每次创建时我都会有一个事务。或者,我可以将它们全部保留在结果对象中并保存到最后,然后将它们添加到项目中并保存项目。但是,这两个选项als都没有过多地使用层叠选项,并且非常复杂,因为它们添加了时间依赖性。 (先保存X,然后保存Y,然后再保存Z)
更新:编码我当前如何添加实体并将其保存到项目中
该项目具有帮助程序方法,该方法仅设置条目(可以设置双向关系,但是在创建条目/事件时不允许Project为null):
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;
}
更新的方法相同,只是在运行模拟方法之前,我先清除了项目中的整个集合。 (并删除所有模拟事件)
答案 0 :(得分:0)
我不会单独保存每个实体。如果与项目一起保存,则可能不会出现问题。级联定义正确,我能够将它们全部添加并保存project
。只需确保建立了双方关系
Project p = new Project();
Entry ntry = new Entry();
Event event = new Event();
p.getEntries().add(ntry);
ntry.setProject(p);// set also other side of relation
ntry.setEvent(event);
p.getEvents().add(event);
event.setProject(p);// set also other side of relation
event.getEntries().add(ntry);
em.persist(p);