@Entity
public class Library {
@Id
private Long id;
@OneToMany
private List<Book> books = new ArrayList<>();
@OneToMany
private Set<Movie> movies = new HashSet<>();
}
This JPQL:
SELECT l FROM Library AS l LEFT JOIN FETCH l.books LEFT JOIN FETCH l.movies WHERE l.id = :id
will return 10 rows if there are 2 books and 5 movies associated with that Library. The session will create a single Library instance, but return 10 duplicate references. Likewise there will be 2 Book instances, with 5 duplicate references to each one in the books collection. movies will not have duplicates because of Setâs inherent filtering.
Iâm curious why Hibernate behaves like this instead of intuitively âboilingâ down to unique references. Is this because of a technical reason, or is there a use-case which requires duplicates?
There are cases where it is impossible to eliminate duplicates when a bag join is involved, since bags are unordered and allow duplicates. So Hibernate doesnât try to be smart and cause you headaches in certain scenarios, but instead just returns you the same cardinality as the JDBC result set. You can tell Hibernate to return unique objects which works by using DISTINCT. Note that the DISTINCT keyword is not necessarily passed to the SQL if you configure this a hint as outlined in the documentation: Hibernate ORM 5.4.29.Final User Guide
DISTINCT de-duplicates the root entity, but it doesnât affect the child collections. In my example, the âbooksâ list will contain 2 unique objects duplicated 5 times each for 10 references total. Even though I called a valid entity query, I received an incorrect representation of the object state. Maybe Iâm misunderstanding something, but this implementation feels misleading. If bag X bag fetches are illegal, then shouldnât any sort of multi-fetch involving a bag be illegal for consistency?