-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
HHH-14730 Test lazy loading of bytecode-enhancement proxy triggered b…
…y loading of a collection with eager references to that proxy
- Loading branch information
Showing
6 changed files
with
386 additions
and
0 deletions.
There are no files selected for viewing
25 changes: 25 additions & 0 deletions
25
...src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/Company.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package org.hibernate.orm.test.mapping.lazytoone.collectioninitializer; | ||
|
||
import javax.persistence.Entity; | ||
import javax.persistence.Id; | ||
|
||
@Entity | ||
public class Company { | ||
@Id | ||
private Long id; | ||
|
||
@Override | ||
public String toString() { | ||
return "Company{" + | ||
"id=" + id + | ||
'}'; | ||
} | ||
|
||
public Long getId() { | ||
return id; | ||
} | ||
|
||
public void setId(Long id) { | ||
this.id = id; | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
.../test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/CostCenter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package org.hibernate.orm.test.mapping.lazytoone.collectioninitializer; | ||
|
||
import javax.persistence.Entity; | ||
import javax.persistence.Id; | ||
import javax.persistence.ManyToOne; | ||
|
||
@Entity | ||
public class CostCenter { | ||
@Id | ||
private Long id; | ||
|
||
@ManyToOne(optional = false) | ||
private Company company; | ||
|
||
@Override | ||
public String toString() { | ||
return "CostCenter{" + | ||
"id=" + id + | ||
", company=" + company + | ||
'}'; | ||
} | ||
|
||
public Long getId() { | ||
return id; | ||
} | ||
|
||
public void setId(Long id) { | ||
this.id = id; | ||
} | ||
|
||
public Company getCompany() { | ||
return company; | ||
} | ||
|
||
public void setCompany(Company company) { | ||
this.company = company; | ||
} | ||
|
||
} |
191 changes: 191 additions & 0 deletions
191
...ollectioninitializer/InitLazyToOneWithinPaddedCollectionInitializationAllowProxyTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
/* | ||
* Hibernate, Relational Persistence for Idiomatic Java | ||
* | ||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later | ||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html | ||
*/ | ||
package org.hibernate.orm.test.mapping.lazytoone.collectioninitializer; | ||
|
||
import org.hibernate.Hibernate; | ||
import org.hibernate.boot.MetadataSources; | ||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder; | ||
import org.hibernate.cfg.AvailableSettings; | ||
import org.hibernate.engine.spi.SessionFactoryImplementor; | ||
|
||
import org.hibernate.testing.TestForIssue; | ||
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; | ||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.hibernate.loader.BatchFetchStyle.PADDED; | ||
|
||
/** | ||
* Test lazy-to-one initialization within a collection initialization, | ||
* with the PADDED batch-fetch-style. | ||
* <p> | ||
* In particular, with Offer having a lazy to-one association to CostCenter, | ||
* and User having a lazy to-many association to UserAuthorization1 and UserAuthorization2, | ||
* and UserAuthorization1 and UserAuthorization2 having an EAGER association to CostCenter, | ||
* test: | ||
* <ul> | ||
* <li>Get a reference to Offer (which will create an uninitialized proxy for CostCenter)</li> | ||
* <li>Get a reference to User</li> | ||
* <li>Initialize User's collection containing UserAuthorization1 and UserAuthorization2, | ||
* which will initialize CostCenter DURING the loading, | ||
* which used to fail because we tried to initialize CostCenter twice | ||
* (once for UserAuthorization1, and once for UserAuthorization2)</li> | ||
* </ul> | ||
*/ | ||
@RunWith(BytecodeEnhancerRunner.class) | ||
@TestForIssue(jiraKey = "HHH-14730") | ||
public class InitLazyToOneWithinPaddedCollectionInitializationAllowProxyTest | ||
extends BaseNonConfigCoreFunctionalTestCase { | ||
|
||
@Override | ||
protected void applyMetadataSources(MetadataSources sources) { | ||
super.applyMetadataSources( sources ); | ||
sources.addAnnotatedClass( User.class ); | ||
sources.addAnnotatedClass( UserAuthorization.class ); | ||
sources.addAnnotatedClass( Company.class ); | ||
sources.addAnnotatedClass( CostCenter.class ); | ||
sources.addAnnotatedClass( Offer.class ); | ||
} | ||
|
||
@Override | ||
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) { | ||
super.configureStandardServiceRegistryBuilder( ssrb ); | ||
ssrb.applySetting( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, true ); | ||
ssrb.applySetting( AvailableSettings.BATCH_FETCH_STYLE, PADDED ); | ||
ssrb.applySetting( AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, 10 ); | ||
} | ||
|
||
@Override | ||
protected void afterSessionFactoryBuilt(SessionFactoryImplementor sessionFactory) { | ||
inTransaction( session -> { | ||
User user0 = new User(); | ||
user0.setId( 0L ); | ||
session.persist( user0 ); | ||
|
||
User user1 = new User(); | ||
user1.setId( 1L ); | ||
session.persist( user1 ); | ||
|
||
User user2 = new User(); | ||
user2.setId( 2L ); | ||
session.persist( user2 ); | ||
|
||
Company company = new Company(); | ||
company.setId( 2L ); | ||
session.persist( company ); | ||
|
||
CostCenter costCenter = new CostCenter(); | ||
costCenter.setId( 3L ); | ||
costCenter.setCompany( company ); | ||
session.persist( costCenter ); | ||
|
||
UserAuthorization user0Authorization1 = new UserAuthorization(); | ||
user0Authorization1.setId( 1L ); | ||
user0Authorization1.setUser( user0 ); | ||
user0Authorization1.setCostCenter( costCenter ); | ||
session.persist( user0Authorization1 ); | ||
|
||
UserAuthorization user1Authorization1 = new UserAuthorization(); | ||
user1Authorization1.setId( 11L ); | ||
user1Authorization1.setUser( user1 ); | ||
user1Authorization1.setCostCenter( costCenter ); | ||
session.persist( user1Authorization1 ); | ||
|
||
UserAuthorization user1Authorization2 = new UserAuthorization(); | ||
user1Authorization2.setId( 12L ); | ||
user1Authorization2.setUser( user1 ); | ||
user1Authorization2.setCostCenter( costCenter ); | ||
session.persist( user1Authorization2 ); | ||
|
||
UserAuthorization user2Authorization1 = new UserAuthorization(); | ||
user2Authorization1.setId( 21L ); | ||
user2Authorization1.setUser( user2 ); | ||
user2Authorization1.setCostCenter( costCenter ); | ||
session.persist( user2Authorization1 ); | ||
|
||
UserAuthorization user2Authorization2 = new UserAuthorization(); | ||
user2Authorization2.setId( 22L ); | ||
user2Authorization2.setUser( user2 ); | ||
user2Authorization2.setCostCenter( costCenter ); | ||
session.persist( user2Authorization2 ); | ||
|
||
UserAuthorization user2Authorization3 = new UserAuthorization(); | ||
user2Authorization3.setId( 23L ); | ||
user2Authorization3.setUser( user2 ); | ||
user2Authorization3.setCostCenter( costCenter ); | ||
session.persist( user2Authorization3 ); | ||
|
||
Offer offer = new Offer(); | ||
offer.setId( 6L ); | ||
offer.setCostCenter( costCenter ); | ||
session.persist( offer ); | ||
} ); | ||
} | ||
|
||
@Test | ||
public void testOneReference() { | ||
inTransaction( (session) -> { | ||
// Add a lazy proxy of the cost center to the persistence context | ||
// through the lazy to-one association from the offer. | ||
Offer offer = session.find( Offer.class, 6L ); | ||
|
||
User user = session.find( User.class, 0L ); | ||
|
||
assertThat( Hibernate.isInitialized( offer.getCostCenter() ) ).isFalse(); | ||
|
||
// Trigger lazy-loading of the cost center | ||
// through the loading of the authorization, | ||
// which contains an eager reference to the cost center. | ||
assertThat( user.getAuthorizations().size() ).isEqualTo( 1 ); | ||
|
||
assertThat( Hibernate.isInitialized( offer.getCostCenter() ) ).isTrue(); | ||
} ); | ||
} | ||
|
||
@Test | ||
public void testTwoReferences() { | ||
inTransaction( (session) -> { | ||
// Add a lazy proxy of the cost center to the persistence context | ||
// through the lazy to-one association from the offer. | ||
Offer offer = session.find( Offer.class, 6L ); | ||
|
||
User user = session.find( User.class, 1L ); | ||
|
||
assertThat( Hibernate.isInitialized( offer.getCostCenter() ) ).isFalse(); | ||
|
||
// Trigger lazy-loading of the cost center | ||
// through the loading of the 2 authorizations, | ||
// which both contain an eager reference to the cost center. | ||
assertThat( user.getAuthorizations().size() ).isEqualTo( 2 ); | ||
|
||
assertThat( Hibernate.isInitialized( offer.getCostCenter() ) ).isTrue(); | ||
} ); | ||
} | ||
|
||
@Test | ||
public void testThreeReferences() { | ||
inTransaction( (session) -> { | ||
// Add a lazy proxy of the cost center to the persistence context | ||
// through the lazy to-one association from the offer. | ||
Offer offer = session.find( Offer.class, 6L ); | ||
|
||
User user = session.find( User.class, 2L ); | ||
|
||
assertThat( Hibernate.isInitialized( offer.getCostCenter() ) ).isFalse(); | ||
|
||
// Trigger lazy-loading of the cost center | ||
// through the loading of the 3 authorizations, | ||
// which all contain an eager reference to the cost center. | ||
assertThat( user.getAuthorizations().size() ).isEqualTo( 3 ); | ||
|
||
assertThat( Hibernate.isInitialized( offer.getCostCenter() ) ).isTrue(); | ||
} ); | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
...e/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/Offer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package org.hibernate.orm.test.mapping.lazytoone.collectioninitializer; | ||
|
||
import javax.persistence.Entity; | ||
import javax.persistence.Id; | ||
import javax.persistence.ManyToOne; | ||
|
||
import static javax.persistence.FetchType.LAZY; | ||
|
||
@Entity | ||
public class Offer { | ||
@Id | ||
private Long id; | ||
|
||
@ManyToOne(fetch = LAZY, optional = false) | ||
private CostCenter costCenter; | ||
|
||
@Override | ||
public String toString() { | ||
return "Offer{" + | ||
"id=" + getId() + | ||
'}'; | ||
} | ||
|
||
public Long getId() { | ||
return id; | ||
} | ||
|
||
public void setId(Long id) { | ||
this.id = id; | ||
} | ||
|
||
public CostCenter getCostCenter() { | ||
return costCenter; | ||
} | ||
|
||
public void setCostCenter(CostCenter costCenter) { | ||
this.costCenter = costCenter; | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
...re/src/test/java/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/User.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package org.hibernate.orm.test.mapping.lazytoone.collectioninitializer; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import javax.persistence.Entity; | ||
import javax.persistence.Id; | ||
import javax.persistence.OneToMany; | ||
import javax.persistence.Table; | ||
|
||
import static javax.persistence.CascadeType.ALL; | ||
|
||
@Entity | ||
@Table(name = "users") | ||
public class User { | ||
@Id | ||
private Long id; | ||
|
||
@OneToMany(mappedBy = "user", cascade = ALL, orphanRemoval = true) | ||
private List<UserAuthorization> authorizations = new ArrayList<>(); | ||
|
||
@Override | ||
public String toString() { | ||
return "User{" + | ||
"id='" + getId() + '\'' + | ||
'}'; | ||
} | ||
|
||
public Long getId() { | ||
return id; | ||
} | ||
|
||
public void setId(Long id) { | ||
this.id = id; | ||
} | ||
|
||
public List<UserAuthorization> getAuthorizations() { | ||
return authorizations; | ||
} | ||
|
||
public void setAuthorizations(List<UserAuthorization> authorizations) { | ||
this.authorizations = authorizations; | ||
} | ||
} |
49 changes: 49 additions & 0 deletions
49
...ava/org/hibernate/orm/test/mapping/lazytoone/collectioninitializer/UserAuthorization.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package org.hibernate.orm.test.mapping.lazytoone.collectioninitializer; | ||
|
||
import javax.persistence.Entity; | ||
import javax.persistence.Id; | ||
import javax.persistence.ManyToOne; | ||
|
||
@Entity | ||
public class UserAuthorization { | ||
@Id | ||
private Long id; | ||
|
||
@ManyToOne(optional = false) | ||
private User user; | ||
|
||
@ManyToOne(optional = false) | ||
private CostCenter costCenter; | ||
|
||
@Override | ||
public String toString() { | ||
return "UserAuthorization{" + | ||
"id='" + getId() + '\'' + | ||
'}'; | ||
} | ||
|
||
public Long getId() { | ||
return id; | ||
} | ||
|
||
public void setId(Long id) { | ||
this.id = id; | ||
} | ||
|
||
public User getUser() { | ||
return user; | ||
} | ||
|
||
public void setUser(User user) { | ||
this.user = user; | ||
} | ||
|
||
public CostCenter getCostCenter() { | ||
return costCenter; | ||
} | ||
|
||
public void setCostCenter(CostCenter costCenter) { | ||
this.costCenter = costCenter; | ||
} | ||
|
||
} |