HHH-15202 Only create SubselectFetch if entity contains subselect fetch config

This commit is contained in:
Christian Beikov 2022-04-11 13:21:44 +02:00
parent 5ec54232a0
commit e5f28ae17a
2 changed files with 131 additions and 0 deletions

View File

@ -157,6 +157,9 @@ public class SubselectFetch {
}
public void addKey(EntityKey key, LoadingEntityEntry entry) {
if ( !entry.getDescriptor().hasSubselectLoadableCollections() ) {
return;
}
final SubselectFetch subselectFetch = subselectFetches.computeIfAbsent(
entry.getEntityInitializer().getNavigablePath(),
navigablePath -> new SubselectFetch(

View File

@ -0,0 +1,128 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.orm.test.batchfetch;
import java.util.List;
import org.hibernate.engine.spi.BatchFetchQueue;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToOne;
import static org.assertj.core.api.Assertions.assertThat;
@DomainModel(
annotatedClasses = {
SubselectFetchTest.Employee.class,
SubselectFetchTest.Task.class
}
)
@SessionFactory
public class SubselectFetchTest {
private static final int NUMBER_OF_EMPLOYEES = 8;
@BeforeEach
public void createData(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
for ( int i = 0; i < NUMBER_OF_EMPLOYEES; i++ ) {
Task mainTask = new Task();
mainTask.id = 100 + i;
session.persist( mainTask );
Task task = new Task();
task.id = i;
task.parentTask = mainTask;
session.persist( task );
Employee e = new Employee( "employee0" + i );
e.task = task;
session.persist( e );
}
}
);
}
@AfterEach
public void deleteData(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery( "delete from Employee" ).executeUpdate();
session.createQuery( "delete from Task where parentTask is not null" ).executeUpdate();
session.createQuery( "delete from Task" ).executeUpdate();
}
);
}
@Test
@TestForIssue( jiraKey = "HHH-15202")
public void testSubselectFetchOnlyCreatedIfEnabled(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
EntityPersister employeePersister = session.getSessionFactory()
.getRuntimeMetamodels()
.getMappingMetamodel()
.getEntityDescriptor( Employee.class );
EntityPersister taskPersister = session.getSessionFactory()
.getRuntimeMetamodels()
.getMappingMetamodel()
.getEntityDescriptor( Task.class );
BatchFetchQueue batchFetchQueue = session.getPersistenceContextInternal().getBatchFetchQueue();
List<Employee> results = session.createQuery( "from Employee e order by e.id", Employee.class ).getResultList();
for ( Employee result : results ) {
assertThat( batchFetchQueue.getSubselect( session.generateEntityKey( result.name, employeePersister ) ) ).isNull();
Task task = session.createQuery( "from Task t where t.employee = :e", Task.class )
.setParameter( "e", result )
.getSingleResult();
assertThat( batchFetchQueue.getSubselect( session.generateEntityKey( task.id, taskPersister ) ) ).isNull();
}
}
);
}
@Entity(name = "Employee")
public static class Employee {
@Id
private String name;
@OneToOne(fetch = FetchType.LAZY)
private Task task;
private Employee() {
}
private Employee(String name) {
this.name = name;
}
}
@Entity(name = "Task")
public static class Task {
@Id
private long id;
@ManyToOne(fetch = FetchType.LAZY)
private Task parentTask;
@OneToOne(fetch = FetchType.LAZY, mappedBy = "task")
private Employee employee;
public Task() {
}
}
}