如何在 @OneToMany 中使用 LinkedHashSet 的插入顺序
How to use the insertion order of a LinkedHashSet in @OneToMany
我拥有的是一个有很多事件的应用程序。这些事件按时间顺序排列,但我得到的只是一个 JSON 事件代码数组,因此数组顺序是它们的添加顺序。
从我在 google 上找到的内容来看,hibernate 似乎更喜欢 Set
s 而不是 List
s 但是使用 Set
我需要维护我选择使用 LinkedHashSet
的条目,因为它维护插入顺序(基于大量的 SO 问题)。
这是我的问题所在。我在 applicationEvent 的序列上设置了一个 OrderBy
,它是该对象的 JSON 数组的索引(插入数据库似乎是随机的,因此使用 Id 不起作用)。查看生成的休眠 SQL 它似乎达到了我的预期。所有事件按序列 1-n 的顺序进行。
然而,当我循环构建列表时,顺序似乎是随机的,不符合我认为适当的插入顺序。
Iterator<ApplicationEventDTO> iter = applicationEvents.iterator();
List<ApplicationEventDTO> list = new ArrayList<ApplicationEventDTO>();
while(iter.hasNext()){
list.add((ApplicationEventDTO) iter.next());
}
应用实体:
@Entity
@Table
public class Application {
//Lots of other stuff
private Set<ApplicationEvent> applicationEvents=new LinkedHashSet<ApplicationEvent>();
@OneToMany (mappedBy = "application", fetch = FetchType.EAGER
, cascade=CascadeType.ALL, orphanRemoval=true)
@NotAudited
@OrderBy("sequence")
public Set<ApplicationEvent> getApplicationEvents() {
return applicationEvents;
}
public void setApplicationEvents(Set<ApplicationEvent> applicationEvents) {
this.applicationEvents = applicationEvents;
}
}
更新
要添加更多信息,是以下文章让我坚持使用集合而不是列表。
https://vladmihalcea.com/hibernate-facts-favoring-sets-vs-bags/
Hibernate cannot simultaneously fetch multiple bags -- 最后的评论表明集合优于列表。
应用实体很大,关系也很多。所有这些似乎都是集合。当尝试将事件更改为列表时,我收到:cannot simultaneously fetch multiple bags
这就是我找到 SO 问题的方式。
我认为您需要将 applicationEvents
集合的类型定义从 Set
更改为 List
。你试过了吗?
示例:
private List<ApplicationEvent> applicationEvents=new ArrayList<>();
//Need to remove FetchType when there are multiple Collections
@OneToMany (mappedBy = "application", cascade=CascadeType.ALL, orphanRemoval=true)
@NotAudited
@OrderBy("sequence")
public List<ApplicationEvent> getApplicationEvents() {
return applicationEvents;
}
尝试三种解决方法中的任何一种
1) 合并子项而不是父项
2) 在合并父项之前保留子项
3) 删除 Cascade.ALL
我拥有的是一个有很多事件的应用程序。这些事件按时间顺序排列,但我得到的只是一个 JSON 事件代码数组,因此数组顺序是它们的添加顺序。
从我在 google 上找到的内容来看,hibernate 似乎更喜欢 Set
s 而不是 List
s 但是使用 Set
我需要维护我选择使用 LinkedHashSet
的条目,因为它维护插入顺序(基于大量的 SO 问题)。
这是我的问题所在。我在 applicationEvent 的序列上设置了一个 OrderBy
,它是该对象的 JSON 数组的索引(插入数据库似乎是随机的,因此使用 Id 不起作用)。查看生成的休眠 SQL 它似乎达到了我的预期。所有事件按序列 1-n 的顺序进行。
然而,当我循环构建列表时,顺序似乎是随机的,不符合我认为适当的插入顺序。
Iterator<ApplicationEventDTO> iter = applicationEvents.iterator();
List<ApplicationEventDTO> list = new ArrayList<ApplicationEventDTO>();
while(iter.hasNext()){
list.add((ApplicationEventDTO) iter.next());
}
应用实体:
@Entity
@Table
public class Application {
//Lots of other stuff
private Set<ApplicationEvent> applicationEvents=new LinkedHashSet<ApplicationEvent>();
@OneToMany (mappedBy = "application", fetch = FetchType.EAGER
, cascade=CascadeType.ALL, orphanRemoval=true)
@NotAudited
@OrderBy("sequence")
public Set<ApplicationEvent> getApplicationEvents() {
return applicationEvents;
}
public void setApplicationEvents(Set<ApplicationEvent> applicationEvents) {
this.applicationEvents = applicationEvents;
}
}
更新
要添加更多信息,是以下文章让我坚持使用集合而不是列表。
https://vladmihalcea.com/hibernate-facts-favoring-sets-vs-bags/
Hibernate cannot simultaneously fetch multiple bags -- 最后的评论表明集合优于列表。
应用实体很大,关系也很多。所有这些似乎都是集合。当尝试将事件更改为列表时,我收到:cannot simultaneously fetch multiple bags
这就是我找到 SO 问题的方式。
我认为您需要将 applicationEvents
集合的类型定义从 Set
更改为 List
。你试过了吗?
示例:
private List<ApplicationEvent> applicationEvents=new ArrayList<>();
//Need to remove FetchType when there are multiple Collections
@OneToMany (mappedBy = "application", cascade=CascadeType.ALL, orphanRemoval=true)
@NotAudited
@OrderBy("sequence")
public List<ApplicationEvent> getApplicationEvents() {
return applicationEvents;
}
尝试三种解决方法中的任何一种
1) 合并子项而不是父项
2) 在合并父项之前保留子项
3) 删除 Cascade.ALL