Skip to content

Commit 5452f9e

Browse files
committed
HHH-19605 Add test for issue
1 parent 70714f8 commit 5452f9e

File tree

1 file changed

+215
-0
lines changed

1 file changed

+215
-0
lines changed
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.dirtiness;
6+
7+
import jakarta.persistence.Entity;
8+
import jakarta.persistence.FetchType;
9+
import jakarta.persistence.Id;
10+
import jakarta.persistence.JoinColumn;
11+
import jakarta.persistence.ManyToOne;
12+
import org.hibernate.Hibernate;
13+
import org.hibernate.annotations.Cache;
14+
import org.hibernate.annotations.CacheConcurrencyStrategy;
15+
import org.hibernate.cache.spi.CacheImplementor;
16+
import org.hibernate.cfg.AvailableSettings;
17+
import org.hibernate.testing.orm.junit.DomainModel;
18+
import org.hibernate.testing.orm.junit.Jira;
19+
import org.hibernate.testing.orm.junit.ServiceRegistry;
20+
import org.hibernate.testing.orm.junit.SessionFactory;
21+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
22+
import org.hibernate.testing.orm.junit.Setting;
23+
import org.junit.jupiter.api.AfterAll;
24+
import org.junit.jupiter.api.BeforeAll;
25+
import org.junit.jupiter.api.Test;
26+
27+
import java.util.List;
28+
29+
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
30+
31+
@DomainModel(annotatedClasses = {
32+
SessionIsDirtyTests.EntityA.class,
33+
SessionIsDirtyTests.EntityB.class,
34+
SessionIsDirtyTests.EntityC.class,
35+
})
36+
@ServiceRegistry(settings = {
37+
@Setting(name = AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, value = "5"),
38+
@Setting(name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "true"),
39+
})
40+
@SessionFactory
41+
@Jira("https://hibernate.atlassian.net/browse/HHH-19605")
42+
public class SessionIsDirtyTests {
43+
@Test
44+
public void testBatchAndCacheDirtiness(SessionFactoryScope scope) {
45+
final CacheImplementor cache = scope.getSessionFactory().getCache();
46+
cache.evictAllRegions();
47+
scope.inTransaction( session -> {
48+
final List<EntityA> resultList = session.createSelectionQuery(
49+
"select a from EntityA a order by a.id",
50+
EntityA.class
51+
).getResultList();
52+
assertThat( session.isDirty() ).isFalse();
53+
54+
assertThat( resultList ).hasSize( 2 );
55+
final EntityA entityA1 = resultList.get( 0 );
56+
assertThat( entityA1.getId() ).isEqualTo( 1L );
57+
assertThat( entityA1.getName() ).isEqualTo( "A1" );
58+
assertThat( entityA1.getEntityB() ).isNull();
59+
60+
final EntityA entityA2 = resultList.get( 1 );
61+
assertThat( entityA2.getId() ).isEqualTo( 2L );
62+
assertThat( entityA2.getName() ).isEqualTo( "A2" );
63+
assertThat( entityA2.getEntityB() ).isNotNull();
64+
assertThat( entityA2.getEntityB().getEntityA() ).isSameAs( entityA1 );
65+
66+
entityA2.getEntityB().setName( "B1 updated" );
67+
assertThat( session.isDirty() ).isTrue();
68+
} );
69+
}
70+
71+
@Test
72+
public void testLazyAssociationDirtiness(SessionFactoryScope scope) {
73+
scope.inTransaction( session -> {
74+
final List<EntityC> resultList = session.createSelectionQuery(
75+
"select c from EntityC c order by c.id",
76+
EntityC.class
77+
).getResultList();
78+
assertThat( session.isDirty() ).isFalse();
79+
80+
assertThat( resultList ).hasSize( 1 );
81+
final EntityC entityC = resultList.get( 0 );
82+
assertThat( entityC.getId() ).isEqualTo( 1L );
83+
assertThat( entityC.getName() ).isEqualTo( "C1" );
84+
assertThat( Hibernate.isInitialized( entityC.getEntityB() ) ).isFalse();
85+
86+
entityC.getEntityB().setName( "B1 lazy updated" );
87+
assertThat( session.isDirty() ).isTrue();
88+
} );
89+
}
90+
91+
@BeforeAll
92+
public void setUp(SessionFactoryScope scope) {
93+
scope.inTransaction( session -> {
94+
final EntityA entityA1 = new EntityA( 1L, "A1" );
95+
final EntityA entityA2 = new EntityA( 2L, "A2" );
96+
final EntityB entityB = new EntityB( 1L, "B1" );
97+
entityB.entityA = entityA1;
98+
entityA2.entityB = entityB;
99+
session.persist( entityA1 );
100+
session.persist( entityA2 );
101+
session.persist( entityB );
102+
103+
final EntityC entityC = new EntityC( 1L, "C1" );
104+
entityC.entityB = entityB;
105+
session.persist( entityC );
106+
} );
107+
}
108+
109+
@AfterAll
110+
public void tearDown(SessionFactoryScope scope) {
111+
scope.getSessionFactory().getSchemaManager().truncateMappedObjects();
112+
}
113+
114+
@Entity(name = "EntityA")
115+
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
116+
static class EntityA {
117+
@Id
118+
Long id;
119+
120+
String name;
121+
122+
@ManyToOne
123+
@JoinColumn(name = "entity_b")
124+
EntityB entityB;
125+
126+
public EntityA() {
127+
}
128+
129+
public EntityA(Long id, String name) {
130+
this.id = id;
131+
this.name = name;
132+
}
133+
134+
public Long getId() {
135+
return id;
136+
}
137+
138+
public String getName() {
139+
return name;
140+
}
141+
142+
public EntityB getEntityB() {
143+
return entityB;
144+
}
145+
}
146+
147+
@Entity(name = "EntityB")
148+
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
149+
static class EntityB {
150+
@Id
151+
Long id;
152+
153+
String name;
154+
155+
@ManyToOne
156+
@JoinColumn(name = "entity_a")
157+
EntityA entityA;
158+
159+
public EntityB() {
160+
}
161+
162+
public EntityB(Long id, String name) {
163+
this.id = id;
164+
this.name = name;
165+
}
166+
167+
public Long getId() {
168+
return id;
169+
}
170+
171+
public String getName() {
172+
return name;
173+
}
174+
175+
public EntityA getEntityA() {
176+
return entityA;
177+
}
178+
179+
public void setName(String name) {
180+
this.name = name;
181+
}
182+
}
183+
184+
@Entity(name = "EntityC")
185+
static class EntityC {
186+
@Id
187+
Long id;
188+
189+
String name;
190+
191+
@ManyToOne(fetch = FetchType.LAZY)
192+
@JoinColumn(name = "entity_b")
193+
EntityB entityB;
194+
195+
public EntityC() {
196+
}
197+
198+
public EntityC(Long id, String name) {
199+
this.id = id;
200+
this.name = name;
201+
}
202+
203+
public Long getId() {
204+
return id;
205+
}
206+
207+
public String getName() {
208+
return name;
209+
}
210+
211+
public EntityB getEntityB() {
212+
return entityB;
213+
}
214+
}
215+
}

0 commit comments

Comments
 (0)