0

What I have is an application that have many events. These events are in chronological order but all I get is a JSON array of eventCodes so the array order is the order in which they were added.

It seems hibernate prefers Sets over Lists from what I can find on google and SO however using a Set I need to maintain order of the entries for which I have chosen to use LinkedHashSet because it maintains insertion order (based on plenty of SO questions).

Which is where my issue is. I have set an OrderBy on sequence of an applicationEvent which is the index of the JSON array for that object (insertion into the DB seems random so using Id did not work). Looking at the hibernate generated SQL it seems to be getting what I expect. All the event in order of Sequence 1-n.

However when I loop to build a list the order seems to be random not respecting what I perceive as the appropriate insertion order.

Iterator<ApplicationEventDTO> iter = applicationEvents.iterator();
List<ApplicationEventDTO> list = new ArrayList<ApplicationEventDTO>();
while(iter.hasNext()){
    list.add((ApplicationEventDTO) iter.next());
}

Application Entity:

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

Update

To add a bit more information it was the below articles that lead me to stick with Sets over Lists.

https://vladmihalcea.com/hibernate-facts-favoring-sets-vs-bags/

Hibernate cannot simultaneously fetch multiple bags -- A comment at the end suggest that Sets are preferable over Lists.

The Application Entity is very large and has many relationships. All of which appear to be Sets. When Attempting to change Events to a List I receive: cannot simultaneously fetch multiple bags which is how I found the SO question.

Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
nerdlyist
  • 2,842
  • 2
  • 20
  • 32
  • Can you post the code of the Entity `ApplicatonEventDTO` ... – Carlitos Way Jul 11 '16 at 19:56
  • @CarlitosWay Added what I think is the important stuff. The code for that is rather large. – nerdlyist Jul 11 '16 at 20:12
  • FWIW It is for the user to decide whether to use Set or List based on whether they want ordering ... not for their JPA provider to impose. – Neil Stockton Jul 12 '16 at 06:48
  • @NeilStockton yes I agree but it seems there are issue with Hibernate and List. I was having issues and when I switched to Sets they were alleviated. I provided this in the answer below: https://vladmihalcea.com/2013/10/16/hibernate-facts-favoring-sets-vs-bags/ – nerdlyist Jul 12 '16 at 12:19

1 Answers1

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

nerdlyist
  • 2,842
  • 2
  • 20
  • 32
Carlitos Way
  • 3,279
  • 20
  • 30
  • Yes I have but as stated from my googling it appears that sets are preferred by hibernate and there are issues with list – nerdlyist Jul 11 '16 at 20:49
  • What kind of issues? I'm asking because, so far, I never had face one before ... and why do you say that hibernate prefers sets over lists? – Carlitos Way Jul 11 '16 at 21:09
  • The main one I was running into was that this is a joint table and Hibernate seems to want to duplicate entries when using lists. You can use FetchType.Eager but that takes a performance hit from what I read and I was getting some crazy database updates I was not expecting. This was the main article that lead me to use `Set` https://vladmihalcea.com/2013/10/16/hibernate-facts-favoring-sets-vs-bags/ – nerdlyist Jul 12 '16 at 01:40
  • Good article, thanks for the reference... However, I'll suggest to apply the workaround that **vlad** says and use List instead: 1) merging the child instead of the parent 2) persisting the children prior to merging the parent 3) removing the Cascade.ALL and use only Cascade.Persist – Carlitos Way Jul 12 '16 at 17:32