[JIRA] (HHH-16405) Eager fields are not fetched when using ScrollableResults
by Orlando Pirlog (JIRA)
Orlando Pirlog ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=5d5277e... ) *created* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiNDRmMTRjZWZk... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-16405?atlOrigin=eyJpIjoiNDRmMT... ) HHH-16405 ( https://hibernate.atlassian.net/browse/HHH-16405?atlOrigin=eyJpIjoiNDRmMT... ) Eager fields are not fetched when using ScrollableResults ( https://hibernate.atlassian.net/browse/HHH-16405?atlOrigin=eyJpIjoiNDRmMT... )
Issue Type: Bug Affects Versions: 5.3.11, 5.6.15 Assignee: Unassigned Components: hibernate-core Created: 30/Mar/2023 07:31 AM Priority: Major Reporter: Orlando Pirlog ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=5d5277e... )
Let’s consider that we have two entities: Course and Student, where Student has many Course(s), a one-to-many relation like in the below example:
@Entity
@Table(name = "courses")
public class Course implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "course_id", unique = true, nullable = false)
protected Integer id;
...
}
@Entity
@Table(name = "students")
public class Student {
@Id
@Column(unique = true, nullable = false)
private Integer studentId;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Course> courses = new ArrayList<>();
...
}
Please note that the courses field in Student is eagerly fetched.
Starting from these entities we’ve generated some entries in the database:
sudentRepo.save(createStudentWithCourses(1, 1, 2));
sudentRepo.save(createStudentWithCourses(2, 3, 4));
Later, we want to retrieve these entities and we have two options:
Option #1 - Everything works as expected we have students with courses.
@Test
public void test_whenUsingList_WorksAsExpected_WithAnyHibernate5_3_11_plus() throws HibernateException {
//obtain session factory
SessionFactory sessionFactory = factory.unwrap(SessionFactory.class);
//open session
Session session = sessionFactory.openSession();
//Obtain students via list()
List<Student> studentList = session
.createQuery("from org.example.Student")
.list();
//close session
session.close();
//expecting to have at least 1 student at index 0
Student student = studentList.get(0);
//expecting to have a course with id 1
Assert.assertEquals(1, student.getCourses().get(0).getId().intValue());
}
Option #2 - Doesn’t work as expected starting with version 5.3.11.Final. We have students… but no courses linked to them.
@Test
public void test_whenUsingScroll_FailsWithLazyInitializationException_StartingWithHibernate5_3_11() throws HibernateException {
//obtain session factory
SessionFactory sessionFactory = factory.unwrap(SessionFactory.class);
//open session
Session session = sessionFactory.openSession();
//Obtain students via ScrollableResults
ScrollableResults scroll = session
.createQuery("from org.example.Student")
.scroll(ScrollMode.FORWARD_ONLY);
ScrollableResultsIterator<Student> iterator = new ScrollableResultsIterator(scroll);
Spliterator spliterator = Spliterators.spliteratorUnknownSize(iterator, 256);
Stream<Student> stream = StreamSupport.stream(spliterator, false);
List<Student> studentList = stream.collect(Collectors.toList());
//close session
session.close();
//expecting to have at least 1 student at index 0
Student student = studentList.get(0);
//expecting to have a course with id 1
Assert.assertEquals(1, student.getCourses().get(0).getId().intValue());
//But what happens is that the following exception is thrown
//org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: org.example.Student.courses, could not initialize proxy - no Session
}
When we need to use the second option, due to performance reasons, we are not able to obtain entities with their EAGER fields fetched and we think this behaviour should be corrected.
Note: (We hope we will not influence your judgment related to this task…)
Debugging inside hibernate code, we’ve found that once with the changes related to https://hibernate.atlassian.net/browse/HHH-11147 the following line was added in org.hibernate.internal. ScrollableResultsImpl # prepareCurrentRow :
private void prepareCurrentRow(boolean underlyingScrollSuccessful) {
...
persistenceContext.beforeLoad();
...
}
which further resulted in having a StatefulPersistenceContext # loadCounter equal with 1, and when StatefulPersistenceContext # initializeNonLazyCollections is invoked nothing is executed due to the first check if ( loadCounter == 0 ) {...
Attached a set of two tests (in AppTest) highlighting the problem.
( https://hibernate.atlassian.net/browse/HHH-16405#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-16405#add-comment?atlOrigin=ey... )
Get Jira notifications on your phone! Download the Jira Cloud app for Android ( https://play.google.com/store/apps/details?id=com.atlassian.android.jira.... ) or iOS ( https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100219- sha1:6a6077b )
1 year, 1 month