Skip to content

Commit 6531109

Browse files
dreab8beikov
authored andcommitted
HHH-17668 Add test for issue
1 parent bfa1a86 commit 6531109

File tree

2 files changed

+360
-0
lines changed

2 files changed

+360
-0
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package org.hibernate.orm.test.bytecode.enhancement.refresh;
2+
3+
import org.hibernate.annotations.Cache;
4+
import org.hibernate.annotations.CacheConcurrencyStrategy;
5+
import org.hibernate.annotations.Fetch;
6+
import org.hibernate.annotations.FetchMode;
7+
8+
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
9+
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
10+
import org.hibernate.testing.orm.junit.JiraKey;
11+
import org.junit.Test;
12+
import org.junit.runner.RunWith;
13+
14+
import jakarta.persistence.Cacheable;
15+
import jakarta.persistence.CascadeType;
16+
import jakarta.persistence.Entity;
17+
import jakarta.persistence.FetchType;
18+
import jakarta.persistence.GeneratedValue;
19+
import jakarta.persistence.Id;
20+
import jakarta.persistence.JoinColumn;
21+
import jakarta.persistence.OneToOne;
22+
23+
@RunWith(BytecodeEnhancerRunner.class)
24+
@JiraKey("HHH-17668")
25+
public class MergeAndRefreshTest extends BaseCoreFunctionalTestCase {
26+
27+
@Override
28+
protected Class[] getAnnotatedClasses() {
29+
return new Class[] {
30+
Phase.class,
31+
PhaseDescription.class
32+
};
33+
}
34+
35+
@Test
36+
public void testRefresh() {
37+
Long phaseId = 1L;
38+
inTransaction(
39+
session -> {
40+
PhaseDescription description = new PhaseDescription("phase 1");
41+
Phase phase = new Phase( phaseId, description );
42+
session.persist( phase );
43+
}
44+
);
45+
46+
Phase phase = fromTransaction(
47+
session -> {
48+
return session.find( Phase.class, phaseId );
49+
}
50+
);
51+
52+
inTransaction(
53+
session -> {
54+
Phase merged = session.merge( phase );
55+
session.refresh( merged );
56+
}
57+
);
58+
}
59+
60+
@Entity(name = "Phase")
61+
@Cacheable
62+
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
63+
public static class Phase {
64+
@Id
65+
private Long id;
66+
67+
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
68+
@JoinColumn(name = "phase_description_id")
69+
private PhaseDescription description;
70+
71+
private String name;
72+
73+
public Phase() {
74+
}
75+
76+
public Phase(Long id, PhaseDescription description) {
77+
this.id = id;
78+
this.description = description;
79+
this.description.phase = this;
80+
}
81+
82+
public Long getId() {
83+
return id;
84+
}
85+
86+
public PhaseDescription getDescription() {
87+
return description;
88+
}
89+
}
90+
91+
@Entity(name = "PhaseDescription")
92+
public static class PhaseDescription {
93+
@Id
94+
@GeneratedValue
95+
private Long id;
96+
97+
private String name;
98+
99+
public PhaseDescription() {
100+
}
101+
102+
public PhaseDescription(String name) {
103+
this.name = name;
104+
}
105+
106+
@OneToOne(mappedBy = "description")
107+
@Fetch(value = FetchMode.SELECT)
108+
private Phase phase;
109+
110+
public Long getId() {
111+
return id;
112+
}
113+
114+
public Phase getPhase() {
115+
return phase;
116+
}
117+
}
118+
}
Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
package org.hibernate.orm.test.locking;
2+
3+
import org.hibernate.Hibernate;
4+
5+
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
6+
import org.hibernate.testing.orm.junit.JiraKey;
7+
import org.hibernate.testing.orm.junit.Jpa;
8+
import org.junit.jupiter.api.BeforeAll;
9+
import org.junit.jupiter.api.Test;
10+
11+
import jakarta.persistence.CascadeType;
12+
import jakarta.persistence.Entity;
13+
import jakarta.persistence.FetchType;
14+
import jakarta.persistence.Id;
15+
import jakarta.persistence.JoinColumn;
16+
import jakarta.persistence.LockModeType;
17+
import jakarta.persistence.OneToOne;
18+
19+
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
20+
import static org.junit.jupiter.api.Assertions.assertEquals;
21+
import static org.junit.jupiter.api.Assertions.assertFalse;
22+
import static org.junit.jupiter.api.Assertions.assertNotNull;
23+
import static org.junit.jupiter.api.Assertions.assertTrue;
24+
25+
@Jpa(
26+
annotatedClasses = {
27+
LockRefreshReferencedAndCascadingTest.MainEntity.class,
28+
LockRefreshReferencedAndCascadingTest.ReferencedEntity.class,
29+
LockRefreshReferencedAndCascadingTest.AnotherReferencedEntity.class,
30+
}
31+
)
32+
public class LockRefreshReferencedAndCascadingTest {
33+
34+
@BeforeAll
35+
public void setUp(EntityManagerFactoryScope scope) {
36+
scope.inTransaction(
37+
entityManager -> {
38+
final AnotherReferencedEntity anotherReferencedEntity = new AnotherReferencedEntity(
39+
1L,
40+
"another lazy"
41+
);
42+
final ReferencedEntity e1 = new ReferencedEntity( 0L, "lazy", anotherReferencedEntity );
43+
final ReferencedEntity e2 = new ReferencedEntity( 1L, "eager", null );
44+
entityManager.persist( e1 );
45+
entityManager.persist( e2 );
46+
final MainEntity e3 = new MainEntity( 0L, e1, e2 );
47+
entityManager.persist( e3 );
48+
}
49+
);
50+
}
51+
52+
@Test
53+
public void testRefreshBeforeRead(EntityManagerFactoryScope scope) {
54+
scope.inTransaction(
55+
entityManager -> {
56+
MainEntity m = entityManager.find( MainEntity.class, 0L );
57+
assertNotNull( m );
58+
ReferencedEntity lazyReference = m.referencedLazy();
59+
ReferencedEntity eagerReference = m.referencedEager();
60+
assertNotNull( lazyReference );
61+
assertNotNull( eagerReference );
62+
assertFalse( Hibernate.isInitialized( lazyReference ) );
63+
64+
// First refresh, then access
65+
entityManager.refresh( eagerReference, LockModeType.PESSIMISTIC_WRITE );
66+
assertFalse( Hibernate.isInitialized( lazyReference ) );
67+
68+
entityManager.refresh( lazyReference, LockModeType.PESSIMISTIC_WRITE );
69+
assertTrue( Hibernate.isInitialized( lazyReference ) );
70+
assertTrue( Hibernate.isInitialized( lazyReference.anotherReferencedEntity ) );
71+
72+
assertEquals( "lazy", lazyReference.status() );
73+
assertEquals( "eager", eagerReference.status() );
74+
assertEquals( LockModeType.PESSIMISTIC_WRITE, entityManager.getLockMode( lazyReference ) );
75+
assertEquals( LockModeType.PESSIMISTIC_WRITE, entityManager.getLockMode( lazyReference.getAnotherReferencedEntity() ) );
76+
assertEquals( LockModeType.PESSIMISTIC_WRITE, entityManager.getLockMode( eagerReference ) );
77+
} );
78+
}
79+
80+
@Test
81+
public void testRefresh(EntityManagerFactoryScope scope) {
82+
scope.inTransaction(
83+
entityManager -> {
84+
MainEntity m = entityManager.find( MainEntity.class, 0L );
85+
assertNotNull( m );
86+
ReferencedEntity lazyReference = m.referencedLazy();
87+
ReferencedEntity eagerReference = m.referencedEager();
88+
assertNotNull( lazyReference );
89+
assertNotNull( eagerReference );
90+
assertFalse( Hibernate.isInitialized( lazyReference ) );
91+
92+
entityManager.refresh( m );
93+
// CascadeType.REFRESH will trigger the initialization
94+
assertTrue( Hibernate.isInitialized( lazyReference ) );
95+
96+
} );
97+
}
98+
99+
@Test
100+
public void testRefreshAfterRead(EntityManagerFactoryScope scope) {
101+
scope.inTransaction(
102+
entityManager -> {
103+
MainEntity m = entityManager.find( MainEntity.class, 0L );
104+
assertNotNull( m );
105+
ReferencedEntity lazyReference = m.referencedLazy();
106+
ReferencedEntity eagerReference = m.referencedEager();
107+
assertNotNull( lazyReference );
108+
assertNotNull( eagerReference );
109+
assertFalse( Hibernate.isInitialized( lazyReference ) );
110+
111+
// First access, the refresh
112+
assertEquals( "lazy", lazyReference.status() );
113+
assertEquals( "eager", eagerReference.status() );
114+
115+
entityManager.refresh( lazyReference, LockModeType.PESSIMISTIC_WRITE );
116+
entityManager.refresh( eagerReference, LockModeType.PESSIMISTIC_WRITE );
117+
118+
assertEquals( LockModeType.PESSIMISTIC_WRITE, entityManager.getLockMode( lazyReference ) );
119+
assertEquals( LockModeType.PESSIMISTIC_WRITE, entityManager.getLockMode( eagerReference ) );
120+
} );
121+
}
122+
123+
@Test
124+
public void testRefreshLockMode(EntityManagerFactoryScope scope) {
125+
scope.inTransaction(
126+
entityManager -> {
127+
MainEntity m = entityManager.find( MainEntity.class, 0L );
128+
assertNotNull( m );
129+
ReferencedEntity lazyReference = m.referencedLazy();
130+
ReferencedEntity eagerReference = m.referencedEager();
131+
assertNotNull( lazyReference );
132+
assertNotNull( eagerReference );
133+
assertFalse( Hibernate.isInitialized( lazyReference ) );
134+
135+
entityManager.refresh( m, LockModeType.PESSIMISTIC_WRITE );
136+
137+
assertTrue( Hibernate.isInitialized( lazyReference ) );
138+
AnotherReferencedEntity anotherReferencedEntity = lazyReference.getAnotherReferencedEntity();
139+
assertTrue( Hibernate.isInitialized( anotherReferencedEntity ) );
140+
141+
assertEquals( LockModeType.PESSIMISTIC_WRITE, entityManager.getLockMode( lazyReference ) );
142+
assertEquals(
143+
LockModeType.PESSIMISTIC_WRITE,
144+
entityManager.getLockMode( anotherReferencedEntity )
145+
);
146+
} );
147+
}
148+
149+
@Test
150+
public void testFindWithLockMode(EntityManagerFactoryScope scope) {
151+
scope.inTransaction(
152+
session -> {
153+
MainEntity mainEntity = session.find( MainEntity.class, 0L, LockModeType.PESSIMISTIC_WRITE );
154+
assertThat( session.getLockMode( mainEntity.referencedEager() ) ).isEqualTo( LockModeType.PESSIMISTIC_WRITE );
155+
}
156+
);
157+
}
158+
159+
@Entity(name = "MainEntity")
160+
public static class MainEntity {
161+
@Id
162+
private Long id;
163+
164+
private String name;
165+
166+
@OneToOne(cascade = { CascadeType.REFRESH }, fetch = FetchType.LAZY)
167+
@JoinColumn(name = "LAZY_COLUMN")
168+
private ReferencedEntity referencedLazy;
169+
170+
@OneToOne(fetch = FetchType.EAGER)
171+
@JoinColumn(name = "EAGER_COLUMN")
172+
private ReferencedEntity referencedEager;
173+
174+
protected MainEntity() {
175+
}
176+
177+
public MainEntity(Long id, ReferencedEntity lazy, ReferencedEntity eager) {
178+
this.id = id;
179+
this.referencedLazy = lazy;
180+
this.referencedEager = eager;
181+
}
182+
183+
public ReferencedEntity referencedLazy() {
184+
return referencedLazy;
185+
}
186+
187+
public ReferencedEntity referencedEager() {
188+
return referencedEager;
189+
}
190+
}
191+
192+
@Entity(name = "ReferencedEntity")
193+
public static class ReferencedEntity {
194+
195+
@Id
196+
private Long id;
197+
198+
private String status;
199+
200+
@OneToOne(cascade = { CascadeType.PERSIST, CascadeType.REFRESH }, fetch = FetchType.LAZY)
201+
private AnotherReferencedEntity anotherReferencedEntity;
202+
203+
protected ReferencedEntity() {
204+
}
205+
206+
public ReferencedEntity(Long id, String status, AnotherReferencedEntity anotherReferencedEntity) {
207+
this.id = id;
208+
this.status = status;
209+
this.anotherReferencedEntity = anotherReferencedEntity;
210+
}
211+
212+
public String status() {
213+
return status;
214+
}
215+
216+
public AnotherReferencedEntity getAnotherReferencedEntity() {
217+
return anotherReferencedEntity;
218+
}
219+
}
220+
221+
@Entity(name = "AnotherReferencedEntity")
222+
public static class AnotherReferencedEntity {
223+
224+
@Id
225+
private Long id;
226+
227+
private String status;
228+
229+
protected AnotherReferencedEntity() {
230+
}
231+
232+
public AnotherReferencedEntity(Long id, String status) {
233+
this.id = id;
234+
this.status = status;
235+
}
236+
237+
public String status() {
238+
return status;
239+
}
240+
}
241+
242+
}

0 commit comments

Comments
 (0)