0
@Entity
@Table(name = "STUDENT")
public class Student {

    private long studentId;
    private String studentName;
    private List<Phone> studentPhoneNumbers;

    ....

    @OneToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "STUDENT_PHONE", joinColumns = { @JoinColumn(name = "STUDENT_ID") }, inverseJoinColumns = { @JoinColumn(name = "PHONE_ID") })
    public List<Phone> getStudentPhoneNumbers() {
        return this.studentPhoneNumbers;
    }

    public void setStudentPhoneNumbers(List<Phone> studentPhoneNumbers) {
        this.studentPhoneNumbers = studentPhoneNumbers;
    }
}

1)

Student student = session.loadStudent(123); // pseudocode
List phoneList = student.getStudentPhoneNumbers();
for (Phone p : phoneList) {
    ...
}

2)

Student student = session.loadStudent(123); // pseudocode
List phoneList = student.getStudentPhoneNumbers();
Iterator itr = phoneList.iterator();   
while(itr.hasNext()) {
    ...
}

I read the answer from here: difference between query.list and query.iterate

Obviously there is difference between list() and iterator() (in Query). What if I use it in the OneToMany list? like the example above, is there difference in term of performance? memory?

Sam YC
  • 10,725
  • 19
  • 102
  • 158
  • @Scary Wombat, how this question duplicate with that one? Hibernate implicitly create proxy wrap up the `List` object, calling these two method may have different impact. – Sam YC Jun 22 '17 at 06:00
  • The two snippets of code you posted do exactly the same thing. The foreach loop of the first snippet uses List.iterator() behind the scene, just like you're doing in the second snippet. That has nothing to do with Hibernate. – JB Nizet Jun 22 '17 at 06:15

2 Answers2

1

It has nothing to do with Hibernate.

When Java Compiler encounters

for (Phone p : phoneList) {
    ....
}

it automatically generate code equivalent to

for (Iterator<Phone> itr = phoneList.iterator(); itr.hasNext();) {
    Phone p = itr.next();
    ....
}

So it is essentially the same for that two examples you are showing.

Adrian Shum
  • 38,812
  • 10
  • 83
  • 131
0

I read up this Hibernate chapter which explain the proxy performance in detail.

The entity's mapping FetchType by default is lazy, which, hibernate will create a proxy around the attribute.

Upon calling list.size() (and etc), hibernate will start to load all the children objects.

If we don't want to load all, we can use the new feature called extra lazy. It will issue select statement for specific record only, for example, list.get(3) select fourth row only.

If we annotate the attribute with eager, then hibernate will load all the children objects (use outer join, which will have duplicate issue) upon it load the parent object. In this case, there is no proxy wrapping around the attribute. It will not have performance difference, not matter we use it as a list or iterator.

Sam YC
  • 10,725
  • 19
  • 102
  • 158
  • What you write about lazy-fetching proxy is correct. However it does ***NOT*** apply to your original question. In your question, you are asking to use for-each loop and iterator to iterate through a collection. There is nothing lazy-fetching proxy is making a difference here. – Adrian Shum Nov 08 '17 at 09:33
  • Ya, it was my mistake, I was not aware of for-each and iterator are the same thing and my example code are a bit confusing, in fact, I was looking for how to retrieve the item one by one or the whole list, and compare the performance. I will edit my question if there is time. thanks reminder. – Sam YC Nov 09 '17 at 07:15
  • What you said is still wrong. Your answer has nothing to do with "one-by-one" vs "whole list". Lazy collection proxy is going to fetch the whole list when accessed – Adrian Shum Nov 09 '17 at 07:36
  • That's why I found the solution `Extra-lazy` will load the record one-by-one. – Sam YC Nov 13 '17 at 02:59