Duplicates in OneToMany annotated List
Asked Answered
D

2

11

I'm working on a Java project using JPA 2 + Hibernate 4.2.6 and I'm getting a strange behaviour.

In my model I have two related entites: Question and Answer

@Entity
public class Question {
    // ...

    @OneToMany(mappedBy = "question", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Set<Answer> answers;

    // ...
}


@Entity
public class Answer {
    // ...

    @ManyToOne(optional = false)
    @JoinColumn(name = "question_id", nullable = false)
    private Question question;

    // ...
}

This works perfectly: all Answers related to a certain Question are loaded correctly.

But now I need to change the tipe of answers collecton from Set to List. I changed the type and ran the application again and now I get several duplicates in answers... Why is it possible? I know that List allows duplicates, but there are no duplicate records in my DB, so why I get these?

I read about some similar bugs in previous version of Hibernate, but I expect they are solved in last version... am I wrong?

NOTE I need to change Set into List because I need to keep information about the order for answers and, possibly, to change this order.

Daughter answered 23/12, 2013 at 19:18 Comment(0)
S
18

You are most likely getting duplicates because when using fetch=FetchType.EAGER, Hibernate uses an outer join to fetch the data in the joined table.

Try removing the eager fetching to confirm. If it is the case, you should either remove the eager fetching, keep a Set instead of a List, or write a JPQL query to retrieve exactly what you need.

From Hibernate doc:

The recommanded approach is to use LAZY on all static fetching definitions and override this choice dynamically through JP-QL.

Speedwriting answered 23/12, 2013 at 19:53 Comment(3)
You can also use @Fetch(FetchMode.SELECT) with fetch=FetchType.EAGER. With this, no need to change from List to Set.Sivie
I was getting 38000 rows where it should have been 38 only. That just killed my ECS instance. Using Set really saved me here. Didn't try @Sivie 's approach. How is it better than just replacing List with Set? How do these two approaches compare in term of efficiency?Verbose
@ParamvirSinghKarwal - If you use a Set you can't have an order (so first answer, second answer, etc). From what I understand, FetchMode.SELECT less efficient.Newmark
I
0

I used Set after noticing it in @Paramvir Singh's comment. It prevented the duplicates records

public class User  {
  
    @OneToMany(fetch = FetchType.EAGER)
    private Set<Role> roles;
    
}
Inbreathe answered 23/8, 2023 at 18:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.