Skip to content

Commit 565693b

Browse files
jimsimon-wkbeikov
authored andcommitted
HHH-19017: Address ClassCastException for PersistentAttributeInterceptable
(cherry picked from commit 98ec951)
1 parent cb89514 commit 565693b

File tree

2 files changed

+145
-20
lines changed

2 files changed

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

0 commit comments

Comments
 (0)