0

I've "Student" and "Class" in relation many to many. In between there is a linking table.

If I want to retrieve all the students with HQL in the following way, everything is fine:

Query queryObject = getSession().createQuery("from Student");
return queryObject.list();          

With the above code if there are three students I get a list of three students.

If I use criterias, however, it's fine only as long as there are no associations in the linking table.

Criteria crit =  getSession().createCriteria(Student.getClass());        
return crit.list();

With the second code, I get three results only when the linking table is empty. However when I add an association, I get 6 results. Looking at the log, Hibernate generates multiple selects. How is it possible?

Can someone explain why does this happen? How can I fix the criteria in order to return the three records only once?

EDIT

In the Student class I mapped in this way:

@ManyToMany(fetch=FetchType.EAGER)
@JoinTable(
    name="room_student_rel"
    , joinColumns={
        @JoinColumn(name="id_student")
        }
    , inverseJoinColumns={
        @JoinColumn(name="id_room")
        }
    )
private List<Room> rooms;

In the room (class) I mapped in this way:

@OneToMany(fetch=FetchType.EAGER,  mappedBy="room")
@Fetch(FetchMode.SELECT)
private List<RoomStudent> roomStudents;
user1883212
  • 7,539
  • 11
  • 46
  • 82
  • What are the 6 results? Can you show the multiple select? – zenbeni Oct 17 '13 at 15:37
  • 1
    I have the feeling that this gets the wrong data because there's an error in the mapping, rather than because there's something missing in the criteria. Can you add the code for the many-to-many mapping? - I would put my money in a missing `mappedBy` property in the annotation – Augusto Oct 17 '13 at 15:38
  • If you add an association, how many rows you have into your table in the db? – Paolo Oct 17 '13 at 15:43
  • Augusto... In the Student class I mapped in this way: @ManyToMany(fetch=FetchType.EAGER) @JoinTable( name="room_student_rel" , joinColumns={ @JoinColumn(name="id_student") } , inverseJoinColumns={ @JoinColumn(name="id_room") } ) private List rooms; In the room (class) I mapped in this way: @OneToMany(fetch=FetchType.EAGER, mappedBy="room") @Fetch(FetchMode.SELECT) private List roomStudents; – user1883212 Oct 17 '13 at 16:19
  • above I added the information in a readable way – user1883212 Oct 17 '13 at 16:25
  • The issue is with the Fetch type being set to Eager. Remove this and try and it should work. Then re-add and have a do some research and you will options see on specifying a transformer to remove duplicates with eager joins. – Alan Hay Oct 17 '13 at 16:41
  • Possible duplicate of [Hibernate query gives same record multiple times](https://stackoverflow.com/questions/10564832/hibernate-query-gives-same-record-multiple-times) – Koray Tugay May 29 '17 at 10:14

1 Answers1

3

To expand on my previous comment, Hibernate will try to select using an outer join when the FetchType is set to EAGER.

See 2.2.5.5 at the following:

http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/

For the implications of this see here:

Hibernate Criteria returns children multiple times with FetchType.EAGER

Now you can also specify a FetchMode (on your criteria.setFetchMode("assocFiled",FetchMode.LAZY) ) to set it to something other than JOIN or you can use something like criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); to filter the duplicates.

Ideally you should avoid EAGER on your entity mappings and where eager fetching is required enable it explicitly on entity load using some hint or via FetchProfile and then deal with the duplicates if required.

Community
  • 1
  • 1
Alan Hay
  • 22,665
  • 4
  • 56
  • 110