Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
HHH-13658 : make NO_PROXY unnecessary
- Better handle `FetchModeType#LAZY` for to-one associations based on whether bytecode-enhancement-as-proxy is enabled. Minimize the cases a user is likely to need to use `@LazyToOne` - See also EAP7-1402
- Loading branch information
Showing
5 changed files
with
408 additions
and
0 deletions.
There are no files selected for viewing
42 changes: 42 additions & 0 deletions
42
hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/Airport.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,42 @@ | ||
/* | ||
* 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; | ||
|
||
import javax.persistence.Entity; | ||
import javax.persistence.Id; | ||
import javax.persistence.Table; | ||
|
||
/** | ||
* @author Steve Ebersole | ||
*/ | ||
@Entity( name = "Airport" ) | ||
@Table( name = "airport" ) | ||
public class Airport { | ||
@Id | ||
private Integer id; | ||
private String code; | ||
|
||
public Airport() { | ||
} | ||
|
||
public Airport(Integer id, String code) { | ||
this.id = id; | ||
this.code = code; | ||
} | ||
|
||
public Integer getId() { | ||
return id; | ||
} | ||
|
||
public String getCode() { | ||
return code; | ||
} | ||
|
||
public void setCode(String code) { | ||
this.code = code; | ||
} | ||
} |
78 changes: 78 additions & 0 deletions
78
hibernate-core/src/test/java/org/hibernate/orm/test/mapping/lazytoone/Flight.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,78 @@ | ||
/* | ||
* 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; | ||
|
||
import javax.persistence.Entity; | ||
import javax.persistence.Id; | ||
import javax.persistence.ManyToOne; | ||
import javax.persistence.Table; | ||
|
||
import org.hibernate.annotations.LazyToOne; | ||
|
||
import static javax.persistence.FetchType.LAZY; | ||
import static org.hibernate.annotations.LazyToOneOption.NO_PROXY; | ||
|
||
/** | ||
* @author Steve Ebersole | ||
*/ | ||
@Entity( name = "Flight" ) | ||
@Table( name = "flight" ) | ||
public class Flight { | ||
@Id | ||
private Integer id; | ||
private String number; | ||
|
||
@ManyToOne( fetch = LAZY ) | ||
private Airport origination; | ||
|
||
@ManyToOne( fetch = LAZY ) | ||
@LazyToOne( NO_PROXY ) | ||
private Airport destination; | ||
|
||
public Flight() { | ||
} | ||
|
||
public Flight(Integer id, String number) { | ||
this.id = id; | ||
this.number = number; | ||
} | ||
|
||
public Flight(Integer id, String number, Airport origination, Airport destination) { | ||
this.id = id; | ||
this.number = number; | ||
this.origination = origination; | ||
this.destination = destination; | ||
} | ||
|
||
public Integer getId() { | ||
return id; | ||
} | ||
|
||
public String getNumber() { | ||
return number; | ||
} | ||
|
||
public void setNumber(String number) { | ||
this.number = number; | ||
} | ||
|
||
public Airport getOrigination() { | ||
return origination; | ||
} | ||
|
||
public void setOrigination(Airport origination) { | ||
this.origination = origination; | ||
} | ||
|
||
public Airport getDestination() { | ||
return destination; | ||
} | ||
|
||
public void setDestination(Airport destination) { | ||
this.destination = destination; | ||
} | ||
} |
94 changes: 94 additions & 0 deletions
94
...ore/src/test/java/org/hibernate/orm/test/mapping/lazytoone/InstrumentedLazyToOneTest.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,94 @@ | ||
/* | ||
* 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; | ||
|
||
import org.hibernate.Hibernate; | ||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder; | ||
import org.hibernate.cfg.AvailableSettings; | ||
import org.hibernate.stat.spi.StatisticsImplementor; | ||
|
||
import org.hibernate.testing.FailureExpected; | ||
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; | ||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; | ||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
|
||
import static org.hamcrest.CoreMatchers.is; | ||
import static org.hamcrest.MatcherAssert.assertThat; | ||
|
||
/** | ||
* Same as {@link LazyToOneTest} except here we have bytecode-enhanced entities | ||
* via {@link BytecodeEnhancerRunner} | ||
*/ | ||
@RunWith( BytecodeEnhancerRunner.class ) | ||
public class InstrumentedLazyToOneTest extends BaseNonConfigCoreFunctionalTestCase { | ||
|
||
@Override | ||
protected Class<?>[] getAnnotatedClasses() { | ||
return new Class[] { Airport.class, Flight.class }; | ||
} | ||
|
||
@Override | ||
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) { | ||
ssrb.applySetting( AvailableSettings.GENERATE_STATISTICS, "true" ); | ||
} | ||
|
||
@Override | ||
protected void prepareTest() throws Exception { | ||
inTransaction( | ||
(session) -> { | ||
final Airport austin = new Airport( 1, "AUS" ); | ||
final Airport baltimore = new Airport( 2, "BWI" ); | ||
|
||
final Flight flight1 = new Flight( 1, "ABC-123", austin, baltimore ); | ||
final Flight flight2 = new Flight( 2, "ABC-987", baltimore, austin ); | ||
|
||
session.persist( austin ); | ||
session.persist( baltimore ); | ||
|
||
session.persist( flight1 ); | ||
session.persist( flight2 ); | ||
} | ||
); | ||
} | ||
|
||
@Override | ||
protected void cleanupTestData() throws Exception { | ||
inTransaction( | ||
(session) -> { | ||
session.createQuery( "delete Flight" ).executeUpdate(); | ||
session.createQuery( "delete Airport" ).executeUpdate(); | ||
} | ||
); | ||
} | ||
|
||
@Test | ||
@FailureExpected( jiraKey = "HHH-13658", message = "Flight#origination is not treated as lazy. Not sure why exactly" ) | ||
public void testEnhancedButProxyNotAllowed() { | ||
final StatisticsImplementor statistics = sessionFactory().getStatistics(); | ||
statistics.clear(); | ||
|
||
inTransaction( | ||
(session) -> { | ||
final Flight flight1 = session.byId( Flight.class ).load( 1 ); | ||
|
||
// unlike the other 2 tests we should get 2 db queries here | ||
assertThat( statistics.getPrepareStatementCount(), is( 2L ) ); | ||
|
||
assertThat( Hibernate.isInitialized( flight1 ), is( true ) ); | ||
|
||
assertThat( Hibernate.isPropertyInitialized( flight1, "origination" ), is( true ) ); | ||
// this should be a non-enhanced proxy | ||
assertThat( Hibernate.isInitialized( flight1.getOrigination() ), is( false ) ); | ||
|
||
assertThat( Hibernate.isPropertyInitialized( flight1, "destination" ), is( false ) ); | ||
// the NO_PROXY here should trigger an EAGER load | ||
assertThat( Hibernate.isInitialized( flight1.getDestination() ), is( false ) ); | ||
} | ||
); | ||
} | ||
} |
104 changes: 104 additions & 0 deletions
104
...rc/test/java/org/hibernate/orm/test/mapping/lazytoone/InstrumentedProxyLazyToOneTest.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,104 @@ | ||
/* | ||
* 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; | ||
|
||
import org.hibernate.Hibernate; | ||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder; | ||
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor; | ||
import org.hibernate.cfg.AvailableSettings; | ||
import org.hibernate.engine.spi.PersistentAttributeInterceptable; | ||
import org.hibernate.stat.spi.StatisticsImplementor; | ||
|
||
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; | ||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; | ||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
|
||
import static org.hamcrest.CoreMatchers.instanceOf; | ||
import static org.hamcrest.CoreMatchers.is; | ||
import static org.hamcrest.CoreMatchers.notNullValue; | ||
import static org.hamcrest.MatcherAssert.assertThat; | ||
|
||
/** | ||
* Same as {@link InstrumentedLazyToOneTest} except here we enable bytecode-enhanced proxies | ||
*/ | ||
@RunWith( BytecodeEnhancerRunner.class ) | ||
public class InstrumentedProxyLazyToOneTest extends BaseNonConfigCoreFunctionalTestCase { | ||
|
||
@Override | ||
protected Class<?>[] getAnnotatedClasses() { | ||
return new Class[] { Airport.class, Flight.class }; | ||
} | ||
|
||
@Override | ||
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) { | ||
ssrb.applySetting( AvailableSettings.GENERATE_STATISTICS, "true" ); | ||
ssrb.applySetting( AvailableSettings.ALLOW_ENHANCEMENT_AS_PROXY, "true" ); | ||
} | ||
|
||
@Override | ||
protected void prepareTest() throws Exception { | ||
inTransaction( | ||
(session) -> { | ||
final Airport austin = new Airport( 1, "AUS" ); | ||
final Airport baltimore = new Airport( 2, "BWI" ); | ||
|
||
final Flight flight1 = new Flight( 1, "ABC-123", austin, baltimore ); | ||
final Flight flight2 = new Flight( 2, "ABC-987", baltimore, austin ); | ||
|
||
session.persist( austin ); | ||
session.persist( baltimore ); | ||
|
||
session.persist( flight1 ); | ||
session.persist( flight2 ); | ||
} | ||
); | ||
} | ||
|
||
@Override | ||
protected void cleanupTestData() throws Exception { | ||
inTransaction( | ||
(session) -> { | ||
session.createQuery( "delete Flight" ).executeUpdate(); | ||
session.createQuery( "delete Airport" ).executeUpdate(); | ||
} | ||
); | ||
} | ||
|
||
@Test | ||
public void testEnhancedWithProxy() { | ||
final StatisticsImplementor statistics = sessionFactory().getStatistics(); | ||
statistics.clear(); | ||
|
||
inTransaction( | ||
(session) -> { | ||
final Flight flight1 = session.byId( Flight.class ).load( 1 ); | ||
|
||
assertThat( statistics.getPrepareStatementCount(), is( 1L ) ); | ||
|
||
assertThat( Hibernate.isInitialized( flight1 ), is( true ) ); | ||
|
||
assertThat( Hibernate.isPropertyInitialized( flight1, "origination" ), is( true ) ); | ||
assertThat( Hibernate.isInitialized( flight1.getOrigination() ), is( false ) ); | ||
// let's make sure these `Hibernate` calls pass for the right reasons... | ||
assertThat( flight1.getOrigination(), instanceOf( PersistentAttributeInterceptable.class ) ); | ||
final PersistentAttributeInterceptable originationProxy = (PersistentAttributeInterceptable) flight1.getOrigination(); | ||
assertThat( originationProxy.$$_hibernate_getInterceptor(), notNullValue() ); | ||
assertThat( originationProxy.$$_hibernate_getInterceptor(), instanceOf( EnhancementAsProxyLazinessInterceptor.class ) ); | ||
|
||
assertThat( Hibernate.isPropertyInitialized( flight1, "destination" ), is( true ) ); | ||
assertThat( Hibernate.isInitialized( flight1.getDestination() ), is( false ) ); | ||
// let's make sure these `Hibernate` calls pass for the right reasons... | ||
assertThat( flight1.getDestination(), instanceOf( PersistentAttributeInterceptable.class ) ); | ||
final PersistentAttributeInterceptable destinationProxy = (PersistentAttributeInterceptable) flight1.getDestination(); | ||
assertThat( destinationProxy.$$_hibernate_getInterceptor(), notNullValue() ); | ||
assertThat( destinationProxy.$$_hibernate_getInterceptor(), instanceOf( EnhancementAsProxyLazinessInterceptor.class ) ); | ||
} | ||
); | ||
} | ||
|
||
} |
Oops, something went wrong.