Skip to content

Commit 4a2d19a

Browse files
committed
HHH-14730 Test lazy loading of bytecode-enhancement proxy triggered by loading of a collection with eager references to that proxy
1 parent 8b02aaf commit 4a2d19a

File tree

6 files changed

+386
-0
lines changed

6 files changed

+386
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.hibernate.orm.test.mapping.lazytoone.collectioninitializer;
2+
3+
import javax.persistence.Entity;
4+
import javax.persistence.Id;
5+
6+
@Entity
7+
public class Company {
8+
@Id
9+
private Long id;
10+
11+
@Override
12+
public String toString() {
13+
return "Company{" +
14+
"id=" + id +
15+
'}';
16+
}
17+
18+
public Long getId() {
19+
return id;
20+
}
21+
22+
public void setId(Long id) {
23+
this.id = id;
24+
}
25+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package org.hibernate.orm.test.mapping.lazytoone.collectioninitializer;
2+
3+
import javax.persistence.Entity;
4+
import javax.persistence.Id;
5+
import javax.persistence.ManyToOne;
6+
7+
@Entity
8+
public class CostCenter {
9+
@Id
10+
private Long id;
11+
12+
@ManyToOne(optional = false)
13+
private Company company;
14+
15+
@Override
16+
public String toString() {
17+
return "CostCenter{" +
18+
"id=" + id +
19+
", company=" + company +
20+
'}';
21+
}
22+
23+
public Long getId() {
24+
return id;
25+
}
26+
27+
public void setId(Long id) {
28+
this.id = id;
29+
}
30+
31+
public Company getCompany() {
32+
return company;
33+
}
34+
35+
public void setCompany(Company company) {
36+
this.company = company;
37+
}
38+
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
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.mapping.lazytoone.collectioninitializer;
8+
9+
import org.hibernate.Hibernate;
10+
import org.hibernate.boot.MetadataSources;
11+
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
12+
import org.hibernate.cfg.AvailableSettings;
13+
import org.hibernate.engine.spi.SessionFactoryImplementor;
14+
15+
import org.hibernate.testing.TestForIssue;
16+
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
17+
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
18+
import org.junit.Before;
19+
import org.junit.Test;
20+
import org.junit.runner.RunWith;
21+
22+
import static org.assertj.core.api.Assertions.assertThat;
23+
import static org.hibernate.loader.BatchFetchStyle.PADDED;
24+
25+
/**
26+
* Test lazy-to-one initialization within a collection initialization,
27+
* with the PADDED batch-fetch-style.
28+
* <p>
29+
* In particular, with Offer having a lazy to-one association to CostCenter,
30+
* and User having a lazy to-many association to UserAuthorization1 and UserAuthorization2,
31+
* and UserAuthorization1 and UserAuthorization2 having an EAGER association to CostCenter,
32+
* test:
33+
* <ul>
34+
* <li>Get a reference to Offer (which will create an uninitialized proxy for CostCenter)</li>
35+
* <li>Get a reference to User</li>
36+
* <li>Initialize User's collection containing UserAuthorization1 and UserAuthorization2,
37+
* which will initialize CostCenter DURING the loading,
38+
* which used to fail because we tried to initialize CostCenter twice
39+
* (once for UserAuthorization1, and once for UserAuthorization2)</li>
40+
* </ul>
41+
*/
42+
@RunWith(BytecodeEnhancerRunner.class)
43+
@TestForIssue(jiraKey = "HHH-14730")
44+
public class InitLazyToOneWithinPaddedCollectionInitializationAllowProxyTest
45+
extends BaseNonConfigCoreFunctionalTestCase {
46+
47+
@Override
48+
protected void applyMetadataSources(MetadataSources sources) {
49+
super.applyMetadataSources( sources );
50+
sources.addAnnotatedClass( User.class );
51+
sources.addAnnotatedClass( UserAuthorization.class );
52+
sources.addAnnotatedClass( Company.class );
53+
sources.addAnnotatedClass( CostCenter.class );
54+
sources.addAnnotatedClass( Offer.class );
55+
}
56+
57+
@Override
58+
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
59+
super.configureStandardServiceRegistryBuilder( ssrb );
60+
ssrb.applySetting( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, true );
61+
ssrb.applySetting( AvailableSettings.BATCH_FETCH_STYLE, PADDED );
62+
ssrb.applySetting( AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, 10 );
63+
}
64+
65+
@Override
66+
protected void afterSessionFactoryBuilt(SessionFactoryImplementor sessionFactory) {
67+
inTransaction( session -> {
68+
User user0 = new User();
69+
user0.setId( 0L );
70+
session.persist( user0 );
71+
72+
User user1 = new User();
73+
user1.setId( 1L );
74+
session.persist( user1 );
75+
76+
User user2 = new User();
77+
user2.setId( 2L );
78+
session.persist( user2 );
79+
80+
Company company = new Company();
81+
company.setId( 2L );
82+
session.persist( company );
83+
84+
CostCenter costCenter = new CostCenter();
85+
costCenter.setId( 3L );
86+
costCenter.setCompany( company );
87+
session.persist( costCenter );
88+
89+
UserAuthorization user0Authorization1 = new UserAuthorization();
90+
user0Authorization1.setId( 1L );
91+
user0Authorization1.setUser( user0 );
92+
user0Authorization1.setCostCenter( costCenter );
93+
session.persist( user0Authorization1 );
94+
95+
UserAuthorization user1Authorization1 = new UserAuthorization();
96+
user1Authorization1.setId( 11L );
97+
user1Authorization1.setUser( user1 );
98+
user1Authorization1.setCostCenter( costCenter );
99+
session.persist( user1Authorization1 );
100+
101+
UserAuthorization user1Authorization2 = new UserAuthorization();
102+
user1Authorization2.setId( 12L );
103+
user1Authorization2.setUser( user1 );
104+
user1Authorization2.setCostCenter( costCenter );
105+
session.persist( user1Authorization2 );
106+
107+
UserAuthorization user2Authorization1 = new UserAuthorization();
108+
user2Authorization1.setId( 21L );
109+
user2Authorization1.setUser( user2 );
110+
user2Authorization1.setCostCenter( costCenter );
111+
session.persist( user2Authorization1 );
112+
113+
UserAuthorization user2Authorization2 = new UserAuthorization();
114+
user2Authorization2.setId( 22L );
115+
user2Authorization2.setUser( user2 );
116+
user2Authorization2.setCostCenter( costCenter );
117+
session.persist( user2Authorization2 );
118+
119+
UserAuthorization user2Authorization3 = new UserAuthorization();
120+
user2Authorization3.setId( 23L );
121+
user2Authorization3.setUser( user2 );
122+
user2Authorization3.setCostCenter( costCenter );
123+
session.persist( user2Authorization3 );
124+
125+
Offer offer = new Offer();
126+
offer.setId( 6L );
127+
offer.setCostCenter( costCenter );
128+
session.persist( offer );
129+
} );
130+
}
131+
132+
@Test
133+
public void testOneReference() {
134+
inTransaction( (session) -> {
135+
// Add a lazy proxy of the cost center to the persistence context
136+
// through the lazy to-one association from the offer.
137+
Offer offer = session.find( Offer.class, 6L );
138+
139+
User user = session.find( User.class, 0L );
140+
141+
assertThat( Hibernate.isInitialized( offer.getCostCenter() ) ).isFalse();
142+
143+
// Trigger lazy-loading of the cost center
144+
// through the loading of the authorization,
145+
// which contains an eager reference to the cost center.
146+
assertThat( user.getAuthorizations().size() ).isEqualTo( 1 );
147+
148+
assertThat( Hibernate.isInitialized( offer.getCostCenter() ) ).isTrue();
149+
} );
150+
}
151+
152+
@Test
153+
public void testTwoReferences() {
154+
inTransaction( (session) -> {
155+
// Add a lazy proxy of the cost center to the persistence context
156+
// through the lazy to-one association from the offer.
157+
Offer offer = session.find( Offer.class, 6L );
158+
159+
User user = session.find( User.class, 1L );
160+
161+
assertThat( Hibernate.isInitialized( offer.getCostCenter() ) ).isFalse();
162+
163+
// Trigger lazy-loading of the cost center
164+
// through the loading of the 2 authorizations,
165+
// which both contain an eager reference to the cost center.
166+
assertThat( user.getAuthorizations().size() ).isEqualTo( 2 );
167+
168+
assertThat( Hibernate.isInitialized( offer.getCostCenter() ) ).isTrue();
169+
} );
170+
}
171+
172+
@Test
173+
public void testThreeReferences() {
174+
inTransaction( (session) -> {
175+
// Add a lazy proxy of the cost center to the persistence context
176+
// through the lazy to-one association from the offer.
177+
Offer offer = session.find( Offer.class, 6L );
178+
179+
User user = session.find( User.class, 2L );
180+
181+
assertThat( Hibernate.isInitialized( offer.getCostCenter() ) ).isFalse();
182+
183+
// Trigger lazy-loading of the cost center
184+
// through the loading of the 3 authorizations,
185+
// which all contain an eager reference to the cost center.
186+
assertThat( user.getAuthorizations().size() ).isEqualTo( 3 );
187+
188+
assertThat( Hibernate.isInitialized( offer.getCostCenter() ) ).isTrue();
189+
} );
190+
}
191+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package org.hibernate.orm.test.mapping.lazytoone.collectioninitializer;
2+
3+
import javax.persistence.Entity;
4+
import javax.persistence.Id;
5+
import javax.persistence.ManyToOne;
6+
7+
import static javax.persistence.FetchType.LAZY;
8+
9+
@Entity
10+
public class Offer {
11+
@Id
12+
private Long id;
13+
14+
@ManyToOne(fetch = LAZY, optional = false)
15+
private CostCenter costCenter;
16+
17+
@Override
18+
public String toString() {
19+
return "Offer{" +
20+
"id=" + getId() +
21+
'}';
22+
}
23+
24+
public Long getId() {
25+
return id;
26+
}
27+
28+
public void setId(Long id) {
29+
this.id = id;
30+
}
31+
32+
public CostCenter getCostCenter() {
33+
return costCenter;
34+
}
35+
36+
public void setCostCenter(CostCenter costCenter) {
37+
this.costCenter = costCenter;
38+
}
39+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package org.hibernate.orm.test.mapping.lazytoone.collectioninitializer;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import javax.persistence.Entity;
6+
import javax.persistence.Id;
7+
import javax.persistence.OneToMany;
8+
import javax.persistence.Table;
9+
10+
import static javax.persistence.CascadeType.ALL;
11+
12+
@Entity
13+
@Table(name = "users")
14+
public class User {
15+
@Id
16+
private Long id;
17+
18+
@OneToMany(mappedBy = "user", cascade = ALL, orphanRemoval = true)
19+
private List<UserAuthorization> authorizations = new ArrayList<>();
20+
21+
@Override
22+
public String toString() {
23+
return "User{" +
24+
"id='" + getId() + '\'' +
25+
'}';
26+
}
27+
28+
public Long getId() {
29+
return id;
30+
}
31+
32+
public void setId(Long id) {
33+
this.id = id;
34+
}
35+
36+
public List<UserAuthorization> getAuthorizations() {
37+
return authorizations;
38+
}
39+
40+
public void setAuthorizations(List<UserAuthorization> authorizations) {
41+
this.authorizations = authorizations;
42+
}
43+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package org.hibernate.orm.test.mapping.lazytoone.collectioninitializer;
2+
3+
import javax.persistence.Entity;
4+
import javax.persistence.Id;
5+
import javax.persistence.ManyToOne;
6+
7+
@Entity
8+
public class UserAuthorization {
9+
@Id
10+
private Long id;
11+
12+
@ManyToOne(optional = false)
13+
private User user;
14+
15+
@ManyToOne(optional = false)
16+
private CostCenter costCenter;
17+
18+
@Override
19+
public String toString() {
20+
return "UserAuthorization{" +
21+
"id='" + getId() + '\'' +
22+
'}';
23+
}
24+
25+
public Long getId() {
26+
return id;
27+
}
28+
29+
public void setId(Long id) {
30+
this.id = id;
31+
}
32+
33+
public User getUser() {
34+
return user;
35+
}
36+
37+
public void setUser(User user) {
38+
this.user = user;
39+
}
40+
41+
public CostCenter getCostCenter() {
42+
return costCenter;
43+
}
44+
45+
public void setCostCenter(CostCenter costCenter) {
46+
this.costCenter = costCenter;
47+
}
48+
49+
}

0 commit comments

Comments
 (0)