如何在@OneToMany中使用LinkedHashSet的插入顺序

时间:2016-07-11 15:37:39

标签: hibernate jpa one-to-many

我所拥有的是一个包含许多事件的应用程序。这些事件按时间顺序排列,但我得到的只是一个eventCodes的JSON数组,因此数组顺序是它们的添加顺序。

似乎hibernate更喜欢Set s List s而不是我在google和SO上找到的东西但是使用Set我需要维护我选择的条目的顺序使用LinkedHashSet因为它维护了插入顺序(基于大量的SO问题)。

我的问题出在哪里。我在applicationEvent的序列上设置了一个OrderBy,它是该对象的JSON数组的索引(插入到数据库中似乎是随机的,所以使用Id不起作用)。看看hibernate生成的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问题的方式。

1 个答案:

答案 0 :(得分:1)

I believe that you need to change the type definition of the applicationEvents Collection, from Set to List. Have you tried that?

Example:

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;
}

Try any of the the three work arounds

1) merging the child instead of the parent

2) persisting the children prior to merging the parent

3) removing the Cascade.ALL