I get different results from the "same query" in Hibernate

Viewed 56

My Case

I have three entities: student, subject and teacher which are structured as follows:

@Entity(name = "Student")
@Table(name = "Student")
public class Student
{
    @Id
    @Column(name = "id")
    private String id;
    
    @Column(name = "name")
    private String name;

    @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name = "student_id")
    private List<Subject> subjectList = new ArrayList<Subject>();

    @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name = "student_id")
    private List<Teacher> teacherList = new ArrayList<Teacher>();
}
@Entity(name = "Subject")
@Table(name = "Subject")
public class Subject
{
    @Id
    @Column(name = "id")
    private Integer id;
    
    @Column(name = "name")
    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "student_id")
    private Student student;
}
@Entity(name = "Teacher")
@Table(name = "Teacher")
public class Teacher
{
    @Id
    @Column(name = "id")
    private Integer id;
    
    @Column(name = "name")
    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "student_id")
    private Student student;
}

Student

id name
A Albert
B Jack

Subject

id name student_id
1 Math A
2 History B
3 Math B
4 English A

Teacher

id name student_id
1 Mr. H B
2 Mr. E B
3 Mr. L A
4 Mr. P A

My Problem

I get two different results based on the type of method I try to get the results back, in fact neither of them is correct.

Method 1

StatelessSession session = getSession();
Student student = (Student) session.get(Student.class, "A");

In this case, the id, name and subjectList properties are returned to me correctly. But teacherList is empty!

Method 2

StatelessSession session = getSession();
Query<V> query = session.createNativeQuery("SELECT * FROM Student WHERE id = :id", Student.class);

List<V> list = query
        .setParameter("id", "A")
        .list();

In this second case, the object inside the list contains the properties: id, name and teacherList. But not subjetList, absurd!

How can I correctly return the "Student" object? What am I doing wrong?

2 Answers

There are two issues:

  • the mapping
  • the stateless session

Remove the @JoinColumn from Student and use mappedBy:

@Entity(name = "Student")
@Table(name = "Student")
public class Student
{
    @Id
    @Column(name = "id")
    private String id;
    
    @Column(name = "name")
    private String name;

    @OneToMany(mappedBy = "student")
    private List<Subject> subjectList = new ArrayList<Subject>();

    @OneToMany(mappedBy = "student")
    private List<Teacher> teacherList = new ArrayList<Teacher>();
}

You can find more examples about mapping bidirectional one-to-many in the documentation.

A stateless session has many limitations, two of which are:

  • Lazy loading of associations is not supported.
  • Collections are ignored by a stateless session.

In this case it would make more sense to use a regular Session. This way lazy loading will work.

Note that mapping an association as eager is usually not recommended unless you know that you always want to load the associations every time you load a student.

Try changing FetchType values from LAZY to EAGER. I think that's the problem. Since FetchType.LAZY mode implies loading data on request. FetchType.EAGER, in turn, loads the data with all the other fields

Related