Skip to content

Commit 98ec951

Browse files
jimsimon-wkbeikov
authored andcommitted
HHH-19017: Address ClassCastException for PersistentAttributeInterceptable
1 parent 8451fe0 commit 98ec951

File tree

2 files changed

+143
-20
lines changed

2 files changed

+143
-20
lines changed

hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.hibernate.engine.spi.EntityKey;
1414
import org.hibernate.engine.spi.EntityUniqueKey;
1515
import org.hibernate.engine.spi.PersistenceContext;
16+
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
1617
import org.hibernate.engine.spi.SharedSessionContractImplementor;
1718
import org.hibernate.graph.GraphSemantic;
1819
import org.hibernate.graph.spi.AppliedGraph;
@@ -198,27 +199,34 @@ public void resolveInstance(EntityDelayedFetchInitializerData data) {
198199
if ( referencedModelPart.isLazy() ) {
199200
instance = UNFETCHED_PROPERTY;
200201
}
201-
else if ( getParent().isEntityInitializer() && isLazyByGraph( rowProcessingState ) ) {
202-
// todo : manage the case when parent is an EmbeddableInitializer
203-
final Object resolvedInstance = getParent().asEntityInitializer()
204-
.getResolvedInstance( rowProcessingState );
205-
final LazyAttributeLoadingInterceptor persistentAttributeInterceptor = (LazyAttributeLoadingInterceptor) ManagedTypeHelper
206-
.asPersistentAttributeInterceptable( resolvedInstance ).$$_hibernate_getInterceptor();
207-
208-
persistentAttributeInterceptor.addLazyFieldByGraph( navigablePath.getLocalName() );
209-
instance = UNFETCHED_PROPERTY;
210-
}
211202
else {
212-
instance = concreteDescriptor.loadByUniqueKey(
213-
uniqueKeyPropertyName,
214-
data.entityIdentifier,
215-
session
216-
);
217-
218-
// If the entity was not in the Persistence Context, but was found now,
219-
// add it to the Persistence Context
220-
if ( instance != null ) {
221-
persistenceContext.addEntity( euk, instance );
203+
// Try to load a PersistentAttributeInterceptable. If we get one, we can add the lazy
204+
// field to the interceptor. If we don't get one, we load the entity by unique key.
205+
PersistentAttributeInterceptable persistentAttributeInterceptable = null;
206+
if ( getParent().isEntityInitializer() && isLazyByGraph( rowProcessingState ) ) {
207+
final Object resolvedInstance =
208+
getParent().asEntityInitializer().getResolvedInstance( rowProcessingState );
209+
persistentAttributeInterceptable =
210+
ManagedTypeHelper.asPersistentAttributeInterceptableOrNull( resolvedInstance );
211+
}
212+
213+
if ( persistentAttributeInterceptable != null ) {
214+
final LazyAttributeLoadingInterceptor persistentAttributeInterceptor = (LazyAttributeLoadingInterceptor) persistentAttributeInterceptable.$$_hibernate_getInterceptor();
215+
persistentAttributeInterceptor.addLazyFieldByGraph( navigablePath.getLocalName() );
216+
instance = UNFETCHED_PROPERTY;
217+
}
218+
else {
219+
instance = concreteDescriptor.loadByUniqueKey(
220+
uniqueKeyPropertyName,
221+
data.entityIdentifier,
222+
session
223+
);
224+
225+
// If the entity was not in the Persistence Context, but was found now,
226+
// add it to the Persistence Context
227+
if ( instance != null ) {
228+
persistenceContext.addEntity( euk, instance );
229+
}
222230
}
223231
}
224232
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* SPDX-License-Identifier: LGPL-2.1-or-later
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.lazyonetoone;
6+
7+
import java.util.List;
8+
9+
import jakarta.persistence.Entity;
10+
import jakarta.persistence.FetchType;
11+
import jakarta.persistence.Id;
12+
import jakarta.persistence.JoinColumn;
13+
import jakarta.persistence.NamedAttributeNode;
14+
import jakarta.persistence.NamedEntityGraph;
15+
import jakarta.persistence.OneToMany;
16+
import jakarta.persistence.OneToOne;
17+
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
18+
import org.hibernate.testing.orm.junit.DomainModel;
19+
import org.hibernate.testing.orm.junit.SessionFactory;
20+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
21+
import org.junit.jupiter.api.AfterAll;
22+
import org.junit.jupiter.api.BeforeAll;
23+
import org.junit.jupiter.api.Test;
24+
25+
import static org.hibernate.Hibernate.isInitialized;
26+
import static org.junit.jupiter.api.Assertions.assertEquals;
27+
import static org.junit.jupiter.api.Assertions.assertTrue;
28+
29+
@DomainModel(
30+
annotatedClasses = {
31+
LazyOneToOneWithEntityGraphTest.Company.class,
32+
LazyOneToOneWithEntityGraphTest.Employee.class,
33+
LazyOneToOneWithEntityGraphTest.Project.class
34+
}
35+
)
36+
@SessionFactory
37+
@BytecodeEnhanced(runNotEnhancedAsWell = true)
38+
public class LazyOneToOneWithEntityGraphTest {
39+
@BeforeAll
40+
void setUp(SessionFactoryScope scope) {
41+
scope.inTransaction(session -> {
42+
// Create company
43+
Company company = new Company();
44+
company.id = 1L;
45+
company.name = "Hibernate";
46+
session.persist(company);
47+
48+
// Create project
49+
Project project = new Project();
50+
project.id = 1L;
51+
session.persist(project);
52+
53+
// Create employee
54+
Employee employee = new Employee();
55+
employee.id = 1L;
56+
employee.company = company;
57+
employee.projects = List.of(project);
58+
session.persist(employee);
59+
});
60+
}
61+
62+
@AfterAll
63+
void tearDown(SessionFactoryScope scope) {
64+
scope.inTransaction(session -> {
65+
scope.getSessionFactory().getSchemaManager().truncateMappedObjects();
66+
});
67+
}
68+
69+
70+
@Test
71+
void reproducerTest(SessionFactoryScope scope) {
72+
scope.inTransaction(session -> {
73+
// Load employee using entity graph
74+
Employee employee = session.createQuery(
75+
"select e from Employee e where e.id = :id", Employee.class)
76+
.setParameter("id", 1L)
77+
.setHint("javax.persistence.fetchgraph", session.getEntityGraph("employee.projects"))
78+
.getSingleResult();
79+
80+
assertTrue(isInitialized(employee.projects));
81+
assertEquals("Hibernate", employee.company.name);
82+
});
83+
}
84+
85+
@Entity(name = "Company")
86+
public static class Company {
87+
@Id
88+
private Long id;
89+
90+
private String name;
91+
}
92+
93+
@Entity(name = "Employee")
94+
@NamedEntityGraph(
95+
name = "employee.projects",
96+
attributeNodes = @NamedAttributeNode("projects")
97+
)
98+
public static class Employee {
99+
@Id
100+
private Long id;
101+
102+
@OneToOne
103+
@JoinColumn(name = "company_name", referencedColumnName = "name")
104+
private Company company;
105+
106+
@OneToMany(fetch = FetchType.LAZY)
107+
private List<Project> projects;
108+
}
109+
110+
@Entity(name = "Project")
111+
public static class Project {
112+
@Id
113+
private Long id;
114+
}
115+
}

0 commit comments

Comments
 (0)