Merge remote-tracking branch 'upstream/main' into wip/6.0

This commit is contained in:
Andrea Boriero 2021-06-10 09:52:24 +02:00
commit 6d59fec436
28 changed files with 599 additions and 171 deletions

View File

@ -926,6 +926,7 @@ Valid options are defined by the `strategy` value of the https://docs.jboss.org/
`*hibernate.hbm2ddl.delimiter*` (e.g. `;`):: `*hibernate.hbm2ddl.delimiter*` (e.g. `;`)::
Identifies the delimiter to use to separate schema management statements in script outputs. Identifies the delimiter to use to separate schema management statements in script outputs.
The default value is `;`.
`*hibernate.schema_management_tool*` (e.g. A schema name):: `*hibernate.schema_management_tool*` (e.g. A schema name)::
Used to specify the `SchemaManagementTool` to use for performing schema management. The default is to use `HibernateSchemaManagementTool`. Used to specify the `SchemaManagementTool` to use for performing schema management. The default is to use `HibernateSchemaManagementTool`.

View File

@ -1967,7 +1967,8 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings {
String HBM2DDL_JDBC_METADATA_EXTRACTOR_STRATEGY = "hibernate.hbm2ddl.jdbc_metadata_extraction_strategy"; String HBM2DDL_JDBC_METADATA_EXTRACTOR_STRATEGY = "hibernate.hbm2ddl.jdbc_metadata_extraction_strategy";
/** /**
* Identifies the delimiter to use to separate schema management statements in script outputs * Identifies the delimiter to use to separate schema management statements in script outputs.
* The default value is <code>;</code>.
*/ */
String HBM2DDL_DELIMITER = "hibernate.hbm2ddl.delimiter"; String HBM2DDL_DELIMITER = "hibernate.hbm2ddl.delimiter";

View File

@ -3298,13 +3298,15 @@ public abstract class AbstractEntityPersister
* without resolving associations or collections. Question: should * without resolving associations or collections. Question: should
* this really be here, or should it be sent back to Loader? * this really be here, or should it be sent back to Loader?
*/ */
@Override
public Object[] hydrate( public Object[] hydrate(
final ResultSet rs, final ResultSet rs,
final Object id, final Object id,
final Object object, final Object object,
final Loadable rootLoadable, final Loadable rootLoadable,
final String[][] suffixedPropertyColumns, final String[][] suffixedPropertyColumns,
final boolean allProperties, final boolean forceEager,
final boolean[] propertiesForceEager,
final SharedSessionContractImplementor session) throws SQLException, HibernateException { final SharedSessionContractImplementor session) throws SQLException, HibernateException {
if ( LOG.isTraceEnabled() ) { if ( LOG.isTraceEnabled() ) {
@ -3366,7 +3368,7 @@ public abstract class AbstractEntityPersister
if ( !propertySelectable[i] ) { if ( !propertySelectable[i] ) {
values[i] = PropertyAccessStrategyBackRefImpl.UNKNOWN; values[i] = PropertyAccessStrategyBackRefImpl.UNKNOWN;
} }
else if ( allProperties || !laziness[i] ) { else if ( forceEager || !laziness[i] || propertiesForceEager != null && propertiesForceEager[i] ) {
//decide which ResultSet to get the property value from: //decide which ResultSet to get the property value from:
final boolean propertyIsDeferred = hasDeferred && final boolean propertyIsDeferred = hasDeferred &&
rootPersister.isSubclassPropertyDeferred( propNames[i], propSubclassNames[i] ); rootPersister.isSubclassPropertyDeferred( propNames[i], propSubclassNames[i] );

View File

@ -79,6 +79,20 @@ public interface Loadable extends EntityPersister {
*/ */
boolean hasRowId(); boolean hasRowId();
/**
* Retrieve property values from one row of a result set
*/
default Object[] hydrate(
ResultSet rs,
Object id,
Object object,
Loadable rootLoadable,
String[][] suffixedPropertyColumns,
boolean forceEager,
SharedSessionContractImplementor session) throws SQLException, HibernateException {
return hydrate( rs, id, object, rootLoadable, suffixedPropertyColumns, forceEager, null, session );
}
/** /**
* Retrieve property values from one row of a result set * Retrieve property values from one row of a result set
*/ */
@ -88,7 +102,8 @@ public interface Loadable extends EntityPersister {
Object object, Object object,
Loadable rootLoadable, Loadable rootLoadable,
String[][] suffixedPropertyColumns, String[][] suffixedPropertyColumns,
boolean allProperties, boolean forceEager,
boolean[] propertiesForceEager,
SharedSessionContractImplementor session) throws SQLException, HibernateException; SharedSessionContractImplementor session) throws SQLException, HibernateException;
boolean isAbstract(); boolean isAbstract();

View File

@ -224,7 +224,7 @@ public class StatisticsImpl implements StatisticsImplementor, Service, Manageabl
public EntityStatisticsImpl getEntityStatistics(String entityName) { public EntityStatisticsImpl getEntityStatistics(String entityName) {
return entityStatsMap.getOrCompute( return entityStatsMap.getOrCompute(
entityName, entityName,
s -> new EntityStatisticsImpl( metamodel.entityPersister( s ) ) this::instantiateEntityStatistics
); );
} }
@ -328,7 +328,7 @@ public class StatisticsImpl implements StatisticsImplementor, Service, Manageabl
public CollectionStatisticsImpl getCollectionStatistics(String role) { public CollectionStatisticsImpl getCollectionStatistics(String role) {
return collectionStatsMap.getOrCompute( return collectionStatsMap.getOrCompute(
role, role,
s -> new CollectionStatisticsImpl( metamodel.collectionPersister( s ) ) this::instantiateCollectionStatistics
); );
} }
@ -416,13 +416,7 @@ public class StatisticsImpl implements StatisticsImplementor, Service, Manageabl
public NaturalIdStatisticsImpl getNaturalIdStatistics(String rootEntityName) { public NaturalIdStatisticsImpl getNaturalIdStatistics(String rootEntityName) {
return naturalIdQueryStatsMap.getOrCompute( return naturalIdQueryStatsMap.getOrCompute(
rootEntityName, rootEntityName,
s -> { this::instantiateNaturalStatistics
final EntityPersister entityDescriptor = metamodel.entityPersister( s );
if ( !entityDescriptor.hasNaturalIdentifier() ) {
throw new IllegalArgumentException( "Given entity [" + s + "] does not define natural-id" );
}
return new NaturalIdStatisticsImpl( entityDescriptor );
}
); );
} }
@ -431,10 +425,7 @@ public class StatisticsImpl implements StatisticsImplementor, Service, Manageabl
final String key = cache.unqualifyRegionName( regionName ); final String key = cache.unqualifyRegionName( regionName );
return deprecatedNaturalIdStatsMap.getOrCompute( return deprecatedNaturalIdStatsMap.getOrCompute(
key, key,
unqualifiedRegionName -> new DeprecatedNaturalIdCacheStatisticsImpl( this::instantiateDeprecatedNaturalIdCacheStatistics
unqualifiedRegionName,
cache.getNaturalIdAccessesInRegion( unqualifiedRegionName )
)
); );
} }
@ -563,21 +554,7 @@ public class StatisticsImpl implements StatisticsImplementor, Service, Manageabl
public CacheRegionStatisticsImpl getDomainDataRegionStatistics(String regionName) { public CacheRegionStatisticsImpl getDomainDataRegionStatistics(String regionName) {
return l2CacheStatsMap.getOrCompute( return l2CacheStatsMap.getOrCompute(
regionName, regionName,
s -> { this::instantiateCacheRegionStatistics
final Region region = cache.getRegion( s );
if ( region == null ) {
throw new IllegalArgumentException( "Unknown cache region : " + s );
}
if ( region instanceof QueryResultsRegion ) {
throw new IllegalArgumentException(
"Region name [" + s + "] referred to a query result region, not a domain data region"
);
}
return new CacheRegionStatisticsImpl( region );
}
); );
} }
@ -608,22 +585,7 @@ public class StatisticsImpl implements StatisticsImplementor, Service, Manageabl
return l2CacheStatsMap.getOrCompute( return l2CacheStatsMap.getOrCompute(
regionName, regionName,
s -> { this::createCacheRegionStatistics
Region region = cache.getRegion( s );
if ( region == null ) {
if ( ! queryCacheEnabled ) {
return null;
}
// this is the pre-5.3 behavior. and since this is a pre-5.3 method it should behave consistently
// NOTE that this method is deprecated
region = cache.getQueryResultsCache( s ).getRegion();
}
return new CacheRegionStatisticsImpl( region );
}
); );
} }
@ -816,7 +778,7 @@ public class StatisticsImpl implements StatisticsImplementor, Service, Manageabl
private CacheRegionStatisticsImpl getQueryRegionStats(String regionName) { private CacheRegionStatisticsImpl getQueryRegionStats(String regionName) {
return l2CacheStatsMap.getOrCompute( return l2CacheStatsMap.getOrCompute(
regionName, regionName,
s -> new CacheRegionStatisticsImpl( cache.getQueryResultsCache( regionName ).getRegion() ) this::instantiateCacheRegionStatsForQueryResults
); );
} }
@ -989,4 +951,64 @@ public class StatisticsImpl implements StatisticsImplementor, Service, Manageabl
.append( ']' ) .append( ']' )
.toString(); .toString();
} }
private EntityStatisticsImpl instantiateEntityStatistics(final String entityName) {
return new EntityStatisticsImpl( metamodel.entityPersister( entityName ) );
}
private CollectionStatisticsImpl instantiateCollectionStatistics(final String role) {
return new CollectionStatisticsImpl( metamodel.collectionPersister( role ) );
}
private NaturalIdStatisticsImpl instantiateNaturalStatistics(final String entityName) {
final EntityPersister entityDescriptor = metamodel.entityPersister( entityName );
if ( !entityDescriptor.hasNaturalIdentifier() ) {
throw new IllegalArgumentException( "Given entity [" + entityName + "] does not define natural-id" );
}
return new NaturalIdStatisticsImpl( entityDescriptor );
}
private DeprecatedNaturalIdCacheStatisticsImpl instantiateDeprecatedNaturalIdCacheStatistics(final String unqualifiedRegionName) {
return new DeprecatedNaturalIdCacheStatisticsImpl(
unqualifiedRegionName,
cache.getNaturalIdAccessesInRegion( unqualifiedRegionName )
);
}
private CacheRegionStatisticsImpl instantiateCacheRegionStatistics(final String regionName) {
final Region region = cache.getRegion( regionName );
if ( region == null ) {
throw new IllegalArgumentException( "Unknown cache region : " + regionName );
}
if ( region instanceof QueryResultsRegion ) {
throw new IllegalArgumentException(
"Region name [" + regionName + "] referred to a query result region, not a domain data region"
);
}
return new CacheRegionStatisticsImpl( region );
}
private CacheRegionStatisticsImpl instantiateCacheRegionStatsForQueryResults(final String regionName) {
return new CacheRegionStatisticsImpl( cache.getQueryResultsCache( regionName ).getRegion() );
}
private CacheRegionStatisticsImpl createCacheRegionStatistics(final String regionName) {
Region region = cache.getRegion( regionName );
if ( region == null ) {
if ( !queryCacheEnabled ) {
return null;
}
// this is the pre-5.3 behavior. and since this is a pre-5.3 method it should behave consistently
// NOTE that this method is deprecated
region = cache.getQueryResultsCache( regionName ).getRegion();
}
return new CacheRegionStatisticsImpl( region );
}
} }

View File

@ -123,7 +123,7 @@ public class HibernateSchemaManagementTool implements SchemaManagementTool, Serv
JdbcContext jdbcContext, JdbcContext jdbcContext,
Map options, Map options,
boolean needsAutoCommit) { boolean needsAutoCommit) {
final String scriptDelimiter = ConfigurationHelper.getString( HBM2DDL_DELIMITER, options ); final String scriptDelimiter = ConfigurationHelper.getString( HBM2DDL_DELIMITER, options, ";" );
final GenerationTarget[] targets = new GenerationTarget[ targetDescriptor.getTargetTypes().size() ]; final GenerationTarget[] targets = new GenerationTarget[ targetDescriptor.getTargetTypes().size() ];
@ -156,7 +156,7 @@ public class HibernateSchemaManagementTool implements SchemaManagementTool, Serv
TargetDescriptor targetDescriptor, TargetDescriptor targetDescriptor,
DdlTransactionIsolator ddlTransactionIsolator, DdlTransactionIsolator ddlTransactionIsolator,
Map options) { Map options) {
final String scriptDelimiter = ConfigurationHelper.getString( HBM2DDL_DELIMITER, options ); final String scriptDelimiter = ConfigurationHelper.getString( HBM2DDL_DELIMITER, options, ";" );
final GenerationTarget[] targets = new GenerationTarget[ targetDescriptor.getTargetTypes().size() ]; final GenerationTarget[] targets = new GenerationTarget[ targetDescriptor.getTargetTypes().size() ];

View File

@ -85,7 +85,7 @@ public class PostgreSQLMultipleSchemaSequenceTest extends BaseUnitTestCase {
); );
try(Statement statement = ddlTransactionIsolator1.getIsolatedConnection().createStatement()) { try(Statement statement = ddlTransactionIsolator1.getIsolatedConnection().createStatement()) {
statement.execute( String.format( "DROP SCHEMA IF EXISTS %s CASCADE", extraSchemaName ) ); statement.execute( String.format( "DROP SCHEMA IF EXISTS %s CASCADE", extraSchemaName ) );
statement.execute( String.format( "CREATE SCHEMA %s", extraSchemaName ) ); statement.execute( String.format( "CREATE SCHEMA %s;", extraSchemaName ) );
try(ResultSet resultSet = statement.executeQuery( "SELECT NEXTVAL('SEQ_TEST')" )) { try(ResultSet resultSet = statement.executeQuery( "SELECT NEXTVAL('SEQ_TEST')" )) {
while ( resultSet.next() ) { while ( resultSet.next() ) {
@ -156,7 +156,7 @@ public class PostgreSQLMultipleSchemaSequenceTest extends BaseUnitTestCase {
assertEquals( 2 , assertEquals( 2 ,
sqlLines sqlLines
.stream() .stream()
.filter( s -> s.equalsIgnoreCase( "create sequence SEQ_TEST start with 1 increment by 1" ) ) .filter( s -> s.equalsIgnoreCase( "create sequence SEQ_TEST start with 1 increment by 1;" ) )
.count() .count()
); );
} }

View File

@ -61,7 +61,7 @@ public class TableCommentTest extends BaseNonConfigCoreFunctionalTestCase {
final String tableName = getTableName(); final String tableName = getTableName();
for ( String sqlStatement : sqlLines ) { for ( String sqlStatement : sqlLines ) {
if ( sqlStatement.toLowerCase() if ( sqlStatement.toLowerCase()
.equals( "comment on table " + tableName.toLowerCase() + " is 'comment snippet'" ) ) { .equals( "comment on table " + tableName.toLowerCase() + " is 'comment snippet';" ) ) {
if ( getDialect().supportsCommentOn() ) { if ( getDialect().supportsCommentOn() ) {
found = true; found = true;
} }

View File

@ -68,12 +68,12 @@ public class SequenceGenerationTest extends BaseUnitTestCase {
List<String> commands = Files.readAllLines( output.toPath() ); List<String> commands = Files.readAllLines( output.toPath() );
assertThat( assertThat(
isCommandGenerated( commands, "create table test_entity \\(id .*, primary key \\(id\\)\\)" ), isCommandGenerated( commands, "create table test_entity \\(id .*, primary key \\(id\\)\\);" ),
is( true ) is( true )
); );
assertThat( assertThat(
isCommandGenerated( commands, "create sequence sequence_generator start with 5 increment by 3" ), isCommandGenerated( commands, "create sequence sequence_generator start with 5 increment by 3;" ),
is( true ) is( true )
); );
} }

View File

@ -70,12 +70,12 @@ public class SequenceGeneratorsTest extends BaseUnitTestCase {
List<String> commands = Files.readAllLines( output.toPath() ); List<String> commands = Files.readAllLines( output.toPath() );
assertThat( assertThat(
isCommandGenerated( commands, "CREATE TABLE TEST_ENTITY \\(ID .*, PRIMARY KEY \\(ID\\)\\)" ), isCommandGenerated( commands, "CREATE TABLE TEST_ENTITY \\(ID .*, PRIMARY KEY \\(ID\\)\\);" ),
is( true ) is( true )
); );
assertThat( assertThat(
isCommandGenerated( commands, "CREATE SEQUENCE SEQUENCE_GENERATOR START WITH 5 INCREMENT BY 3" ), isCommandGenerated( commands, "CREATE SEQUENCE SEQUENCE_GENERATOR START WITH 5 INCREMENT BY 3;" ),
is( true ) is( true )
); );
} }

View File

@ -71,13 +71,13 @@ public class TableGeneratorTest extends BaseUnitTestCase {
final List<String> commands = Files.readAllLines( output.toPath() ); final List<String> commands = Files.readAllLines( output.toPath() );
final String expectedTestEntityTableCreationCommand = "CREATE TABLE TEST_ENTITY \\(ID .*, PRIMARY KEY \\(ID\\)\\)"; final String expectedTestEntityTableCreationCommand = "CREATE TABLE TEST_ENTITY \\(ID .*, PRIMARY KEY \\(ID\\)\\);";
assertTrue( assertTrue(
"The command '" + expectedTestEntityTableCreationCommand + "' has not been correctly generated", "The command '" + expectedTestEntityTableCreationCommand + "' has not been correctly generated",
isCommandGenerated( commands, expectedTestEntityTableCreationCommand ) isCommandGenerated( commands, expectedTestEntityTableCreationCommand )
); );
final String expectedIdTableGeneratorCreationCommand = "CREATE TABLE ID_TABLE_GENERATOR \\(PK .*, VALUE .*, PRIMARY KEY \\(PK\\)\\)"; final String expectedIdTableGeneratorCreationCommand = "CREATE TABLE ID_TABLE_GENERATOR \\(PK .*, VALUE .*, PRIMARY KEY \\(PK\\)\\);";
assertTrue( assertTrue(
"The command '" + expectedIdTableGeneratorCreationCommand + "' has not been correctly generated", "The command '" + expectedIdTableGeneratorCreationCommand + "' has not been correctly generated",
@ -88,7 +88,7 @@ public class TableGeneratorTest extends BaseUnitTestCase {
) )
); );
final String expectedInsertIntoTableGeneratorCommand = "INSERT INTO ID_TABLE_GENERATOR\\(PK, VALUE\\) VALUES \\('TEST_ENTITY_ID'," + EXPECTED_DB_INSERTED_VALUE + "\\)"; final String expectedInsertIntoTableGeneratorCommand = "INSERT INTO ID_TABLE_GENERATOR\\(PK, VALUE\\) VALUES \\('TEST_ENTITY_ID'," + EXPECTED_DB_INSERTED_VALUE + "\\);";
assertTrue( assertTrue(
"The command '" + expectedInsertIntoTableGeneratorCommand + "' has not been correctly generated", "The command '" + expectedInsertIntoTableGeneratorCommand + "' has not been correctly generated",

View File

@ -72,13 +72,13 @@ public class TableGeneratorsTest extends BaseUnitTestCase {
final List<String> commands = Files.readAllLines( output.toPath() ); final List<String> commands = Files.readAllLines( output.toPath() );
final String expectedTestEntityTableCreationCommand = "CREATE TABLE TEST_ENTITY \\(ID .*, PRIMARY KEY \\(ID\\)\\)"; final String expectedTestEntityTableCreationCommand = "CREATE TABLE TEST_ENTITY \\(ID .*, PRIMARY KEY \\(ID\\)\\);";
assertTrue( assertTrue(
"The command '" + expectedTestEntityTableCreationCommand + "' has not been correctly generated", "The command '" + expectedTestEntityTableCreationCommand + "' has not been correctly generated",
isCommandGenerated( commands, expectedTestEntityTableCreationCommand ) isCommandGenerated( commands, expectedTestEntityTableCreationCommand )
); );
final String expectedIdTableGeneratorCreationCommand = "CREATE TABLE ID_TABLE_GENERATOR \\(PK .*, VALUE .*, PRIMARY KEY \\(PK\\)\\)"; final String expectedIdTableGeneratorCreationCommand = "CREATE TABLE ID_TABLE_GENERATOR \\(PK .*, VALUE .*, PRIMARY KEY \\(PK\\)\\);";
assertTrue( assertTrue(
"The command '" + expectedIdTableGeneratorCreationCommand + "' has not been correctly generated", "The command '" + expectedIdTableGeneratorCreationCommand + "' has not been correctly generated",
@ -89,7 +89,7 @@ public class TableGeneratorsTest extends BaseUnitTestCase {
) )
); );
final String expectedInsertIntoTableGeneratorCommand = "INSERT INTO ID_TABLE_GENERATOR\\(PK, VALUE\\) VALUES \\('TEST_ENTITY_ID'," + EXPECTED_DB_INSERTED_VALUE + "\\)"; final String expectedInsertIntoTableGeneratorCommand = "INSERT INTO ID_TABLE_GENERATOR\\(PK, VALUE\\) VALUES \\('TEST_ENTITY_ID'," + EXPECTED_DB_INSERTED_VALUE + "\\);";
assertTrue( assertTrue(
"The command '" + expectedInsertIntoTableGeneratorCommand + "' has not been correctly generated", "The command '" + expectedInsertIntoTableGeneratorCommand + "' has not been correctly generated",

View File

@ -93,7 +93,7 @@ public class UniqueConstraintGenerationTest {
private boolean isUniqueConstraintGenerated(String tableName, String columnName) throws IOException { private boolean isUniqueConstraintGenerated(String tableName, String columnName) throws IOException {
boolean matches = false; boolean matches = false;
final String regex = getDialect().getAlterTableString( tableName ) + " add constraint uk_(.)* unique \\(" + columnName + "\\)"; final String regex = getDialect().getAlterTableString( tableName ) + " add constraint uk_(.)* unique \\(" + columnName + "\\);";
final String fileContent = new String( Files.readAllBytes( output.toPath() ) ).toLowerCase(); final String fileContent = new String( Files.readAllBytes( output.toPath() ) ).toLowerCase();
final String[] split = fileContent.split( System.lineSeparator() ); final String[] split = fileContent.split( System.lineSeparator() );
@ -109,7 +109,7 @@ public class UniqueConstraintGenerationTest {
private boolean isCreateUniqueIndexGenerated(String tableName, String columnName) throws IOException { private boolean isCreateUniqueIndexGenerated(String tableName, String columnName) throws IOException {
boolean matches = false; boolean matches = false;
String regex = "create unique index uk_(.)* on " + tableName + " \\(" + columnName + "\\)"; String regex = "create unique index uk_(.)* on " + tableName + " \\(" + columnName + "\\);";
final String fileContent = new String( Files.readAllBytes( output.toPath() ) ).toLowerCase(); final String fileContent = new String( Files.readAllBytes( output.toPath() ) ).toLowerCase();
final String[] split = fileContent.split( System.lineSeparator() ); final String[] split = fileContent.split( System.lineSeparator() );

View File

@ -26,6 +26,7 @@ import javax.persistence.criteria.JoinType;
import java.util.List; import java.util.List;
import static org.hibernate.Hibernate.isInitialized; import static org.hibernate.Hibernate.isInitialized;
import static org.hibernate.Hibernate.isPropertyInitialized;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@ -142,6 +143,11 @@ public class HHH3949Test extends BaseCoreFunctionalTestCase {
for ( Person person : persons ) { for ( Person person : persons ) {
assertTrue( isInitialized( person ) ); assertTrue( isInitialized( person ) );
if ( shouldHaveVehicle( person ) ) { if ( shouldHaveVehicle( person ) ) {
// We used a "join fetch", so the vehicle must be initialized
// before we even call the getter
// (which could trigger lazy initialization if the join fetch didn't work).
assertTrue( isPropertyInitialized( person, "vehicle" ) );
assertNotNull( person.getVehicle() ); assertNotNull( person.getVehicle() );
assertTrue( isInitialized( person.getVehicle() ) ); assertTrue( isInitialized( person.getVehicle() ) );
assertNotNull( person.getVehicle().getDriver() ); assertNotNull( person.getVehicle().getDriver() );
@ -157,6 +163,11 @@ public class HHH3949Test extends BaseCoreFunctionalTestCase {
} }
for ( Vehicle vehicle : vehicles ) { for ( Vehicle vehicle : vehicles ) {
if ( shouldHaveDriver( vehicle ) ) { if ( shouldHaveDriver( vehicle ) ) {
// We used a "join fetch", so the drover must be initialized
// before we even call the getter
// (which could trigger lazy initialization if the join fetch didn't work).
assertTrue( isPropertyInitialized( vehicle, "driver" ) );
assertNotNull( vehicle.getDriver() ); assertNotNull( vehicle.getDriver() );
assertNotNull( vehicle.getDriver().getVehicle() ); assertNotNull( vehicle.getDriver().getVehicle() );
} }

View File

@ -20,12 +20,17 @@ import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInter
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor; import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata; import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.BeforeClassOnce;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions; import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
import org.hibernate.testing.jdbc.SQLStatementInterceptor; import org.hibernate.testing.jdbc.SQLStatementInterceptor;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -36,6 +41,7 @@ import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hibernate.annotations.FetchMode.JOIN; import static org.hibernate.annotations.FetchMode.JOIN;
import static org.junit.Assert.assertTrue;
/** /**
* Test for lazy uni-directional to-one (with JOIN fetching) when enhanced proxies are allowed * Test for lazy uni-directional to-one (with JOIN fetching) when enhanced proxies are allowed
@ -61,17 +67,6 @@ public class JoinFetchedManyToOneAllowProxyTests extends BaseNonConfigCoreFuncti
@Test @Test
public void testOwnerIsProxy() { public void testOwnerIsProxy() {
inTransaction(
(session) -> {
final Customer customer = new Customer( 1, "Acme Brick" );
session.persist( customer );
final Order order = new Order( 1, customer, BigDecimal.ONE );
session.persist( order );
}
);
sqlStatementInterceptor.clear();
final EntityPersister orderDescriptor = sessionFactory().getMetamodel().entityPersister( Order.class ); final EntityPersister orderDescriptor = sessionFactory().getMetamodel().entityPersister( Order.class );
final BytecodeEnhancementMetadata orderEnhancementMetadata = orderDescriptor.getBytecodeEnhancementMetadata(); final BytecodeEnhancementMetadata orderEnhancementMetadata = orderDescriptor.getBytecodeEnhancementMetadata();
assertThat( orderEnhancementMetadata.isEnhancedForLazyLoading(), is( true ) ); assertThat( orderEnhancementMetadata.isEnhancedForLazyLoading(), is( true ) );
@ -116,6 +111,50 @@ public class JoinFetchedManyToOneAllowProxyTests extends BaseNonConfigCoreFuncti
); );
} }
@Test
@TestForIssue(jiraKey = "HHH-14659")
public void testQueryJoinFetch() {
Order order = fromTransaction( (session) -> {
final Order result = session.createQuery(
"select o from Order o join fetch o.customer",
Order.class )
.uniqueResult();
assertThat( sqlStatementInterceptor.getSqlQueries().size(), is( 1 ) );
return result;
} );
// The "join fetch" should have already initialized the property,
// so that the getter can safely be called outside of a session.
assertTrue( Hibernate.isPropertyInitialized( order, "customer" ) );
// The "join fetch" should have already initialized the associated entity.
Customer customer = order.getCustomer();
assertTrue( Hibernate.isInitialized( customer ) );
assertThat( sqlStatementInterceptor.getSqlQueries().size(), is( 1 ) );
}
@Before
public void createTestData() {
inTransaction(
(session) -> {
final Customer customer = new Customer( 1, "Acme Brick" );
session.persist( customer );
final Order order = new Order( 1, customer, BigDecimal.ONE );
session.persist( order );
}
);
sqlStatementInterceptor.clear();
}
@After
public void dropTestData() {
inTransaction(
(session) -> {
session.createQuery( "delete Order" ).executeUpdate();
session.createQuery( "delete Customer" ).executeUpdate();
}
);
}
@Entity( name = "Customer" ) @Entity( name = "Customer" )
@Table( name = "customer" ) @Table( name = "customer" )
public static class Customer { public static class Customer {

View File

@ -12,6 +12,7 @@ import javax.persistence.Id;
import javax.persistence.ManyToOne; import javax.persistence.ManyToOne;
import javax.persistence.Table; import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.boot.MetadataSources; import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor; import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor;
@ -19,8 +20,10 @@ import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLaziness
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor; import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata; import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions; import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
import org.hibernate.testing.jdbc.SQLStatementInterceptor; import org.hibernate.testing.jdbc.SQLStatementInterceptor;
@ -36,6 +39,7 @@ import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertTrue;
/** /**
* Test for lazy uni-directional to-one (with SELECT fetching) when enhanced proxies are allowed * Test for lazy uni-directional to-one (with SELECT fetching) when enhanced proxies are allowed
@ -61,8 +65,6 @@ public class ManyToOneAllowProxyTests extends BaseNonConfigCoreFunctionalTestCas
@Test @Test
public void testOwnerIsProxy() { public void testOwnerIsProxy() {
sqlStatementInterceptor.clear();
final EntityPersister orderDescriptor = sessionFactory().getMetamodel().entityPersister( Order.class ); final EntityPersister orderDescriptor = sessionFactory().getMetamodel().entityPersister( Order.class );
final BytecodeEnhancementMetadata orderEnhancementMetadata = orderDescriptor.getBytecodeEnhancementMetadata(); final BytecodeEnhancementMetadata orderEnhancementMetadata = orderDescriptor.getBytecodeEnhancementMetadata();
assertThat( orderEnhancementMetadata.isEnhancedForLazyLoading(), is( true ) ); assertThat( orderEnhancementMetadata.isEnhancedForLazyLoading(), is( true ) );
@ -115,6 +117,27 @@ public class ManyToOneAllowProxyTests extends BaseNonConfigCoreFunctionalTestCas
); );
} }
@Test
@TestForIssue(jiraKey = "HHH-14659")
public void testQueryJoinFetch() {
Order order = fromTransaction( (session) -> {
final Order result = session.createQuery(
"select o from Order o join fetch o.customer",
Order.class )
.uniqueResult();
assertThat( sqlStatementInterceptor.getSqlQueries().size(), is( 1 ) );
return result;
} );
// The "join fetch" should have already initialized the property,
// so that the getter can safely be called outside of a session.
assertTrue( Hibernate.isPropertyInitialized( order, "customer" ) );
// The "join fetch" should have already initialized the associated entity.
Customer customer = order.getCustomer();
assertTrue( Hibernate.isInitialized( customer ) );
assertThat( sqlStatementInterceptor.getSqlQueries().size(), is( 1 ) );
}
@Before @Before
public void createTestData() { public void createTestData() {
inTransaction( inTransaction(
@ -125,6 +148,7 @@ public class ManyToOneAllowProxyTests extends BaseNonConfigCoreFunctionalTestCas
session.persist( order ); session.persist( order );
} }
); );
sqlStatementInterceptor.clear();
} }
@After @After

View File

@ -12,6 +12,7 @@ import javax.persistence.Id;
import javax.persistence.ManyToOne; import javax.persistence.ManyToOne;
import javax.persistence.Table; import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.annotations.LazyToOne; import org.hibernate.annotations.LazyToOne;
import org.hibernate.boot.MetadataSources; import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
@ -22,11 +23,13 @@ import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions; import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
import org.hibernate.testing.jdbc.SQLStatementInterceptor; import org.hibernate.testing.jdbc.SQLStatementInterceptor;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.After; import org.junit.After;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -37,6 +40,7 @@ import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hibernate.annotations.LazyToOneOption.NO_PROXY; import static org.hibernate.annotations.LazyToOneOption.NO_PROXY;
import static org.junit.Assert.assertTrue;
/** /**
* Baseline test for uni-directional to-one, using an explicit @LazyToOne(NO_PROXY) * Baseline test for uni-directional to-one, using an explicit @LazyToOne(NO_PROXY)
@ -64,17 +68,6 @@ public class ManyToOneExplicitOptionTests extends BaseNonConfigCoreFunctionalTes
@Test @Test
public void testOwnerIsProxy() { public void testOwnerIsProxy() {
inTransaction(
(session) -> {
final Customer customer = new Customer( 1, "Acme Brick" );
session.persist( customer );
final Order order = new Order( 1, customer, BigDecimal.ONE );
session.persist( order );
}
);
sqlStatementInterceptor.clear();
final EntityPersister orderDescriptor = sessionFactory().getMetamodel().entityPersister( Order.class ); final EntityPersister orderDescriptor = sessionFactory().getMetamodel().entityPersister( Order.class );
final BytecodeEnhancementMetadata orderEnhancementMetadata = orderDescriptor.getBytecodeEnhancementMetadata(); final BytecodeEnhancementMetadata orderEnhancementMetadata = orderDescriptor.getBytecodeEnhancementMetadata();
assertThat( orderEnhancementMetadata.isEnhancedForLazyLoading(), is( true ) ); assertThat( orderEnhancementMetadata.isEnhancedForLazyLoading(), is( true ) );
@ -127,6 +120,40 @@ public class ManyToOneExplicitOptionTests extends BaseNonConfigCoreFunctionalTes
); );
} }
@Test
@TestForIssue(jiraKey = "HHH-14659")
public void testQueryJoinFetch() {
Order order = fromTransaction( (session) -> {
final Order result = session.createQuery(
"select o from Order o join fetch o.customer",
Order.class )
.uniqueResult();
assertThat( sqlStatementInterceptor.getSqlQueries().size(), is( 1 ) );
return result;
} );
// The "join fetch" should have already initialized the property,
// so that the getter can safely be called outside of a session.
assertTrue( Hibernate.isPropertyInitialized( order, "customer" ) );
// The "join fetch" should have already initialized the associated entity.
Customer customer = order.getCustomer();
assertTrue( Hibernate.isInitialized( customer ) );
assertThat( sqlStatementInterceptor.getSqlQueries().size(), is( 1 ) );
}
@Before
public void createTestData() {
inTransaction(
(session) -> {
final Customer customer = new Customer( 1, "Acme Brick" );
session.persist( customer );
final Order order = new Order( 1, customer, BigDecimal.ONE );
session.persist( order );
}
);
sqlStatementInterceptor.clear();
}
@After @After
public void dropTestData() { public void dropTestData() {
inTransaction( inTransaction(

View File

@ -11,6 +11,7 @@ import javax.persistence.Id;
import javax.persistence.OneToOne; import javax.persistence.OneToOne;
import javax.persistence.Table; import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.boot.MetadataSources; import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor; import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor;
@ -20,6 +21,7 @@ import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions; import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
import org.hibernate.testing.jdbc.SQLStatementInterceptor; import org.hibernate.testing.jdbc.SQLStatementInterceptor;
@ -35,6 +37,7 @@ import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertTrue;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -60,8 +63,6 @@ public class InverseToOneAllowProxyTests extends BaseNonConfigCoreFunctionalTest
@Test @Test
public void testOwnerIsProxy() { public void testOwnerIsProxy() {
sqlStatementInterceptor.clear();
final EntityPersister supplementalInfoDescriptor = sessionFactory().getMetamodel().entityPersister( SupplementalInfo.class ); final EntityPersister supplementalInfoDescriptor = sessionFactory().getMetamodel().entityPersister( SupplementalInfo.class );
final BytecodeEnhancementMetadata supplementalInfoEnhancementMetadata = supplementalInfoDescriptor.getBytecodeEnhancementMetadata(); final BytecodeEnhancementMetadata supplementalInfoEnhancementMetadata = supplementalInfoDescriptor.getBytecodeEnhancementMetadata();
assertThat( supplementalInfoEnhancementMetadata.isEnhancedForLazyLoading(), is( true ) ); assertThat( supplementalInfoEnhancementMetadata.isEnhancedForLazyLoading(), is( true ) );
@ -113,6 +114,27 @@ public class InverseToOneAllowProxyTests extends BaseNonConfigCoreFunctionalTest
); );
} }
@Test
@TestForIssue(jiraKey = "HHH-14659")
public void testQueryJoinFetch() {
SupplementalInfo info = fromTransaction( (session) -> {
final SupplementalInfo result = session.createQuery(
"select s from SupplementalInfo s join fetch s.customer",
SupplementalInfo.class )
.uniqueResult();
assertThat( sqlStatementInterceptor.getSqlQueries().size(), is( 1 ) );
return result;
} );
// The "join fetch" should have already initialized the property,
// so that the getter can safely be called outside of a session.
assertTrue( Hibernate.isPropertyInitialized( info, "customer" ) );
// The "join fetch" should have already initialized the associated entity.
Customer customer = info.getCustomer();
assertTrue( Hibernate.isInitialized( customer ) );
assertThat( sqlStatementInterceptor.getSqlQueries().size(), is( 1 ) );
}
@Before @Before
public void createTestData() { public void createTestData() {
inTransaction( inTransaction(
@ -123,6 +145,7 @@ public class InverseToOneAllowProxyTests extends BaseNonConfigCoreFunctionalTest
session.persist( supplementalInfo ); session.persist( supplementalInfo );
} }
); );
sqlStatementInterceptor.clear();
} }
@After @After

View File

@ -11,6 +11,7 @@ import javax.persistence.Id;
import javax.persistence.OneToOne; import javax.persistence.OneToOne;
import javax.persistence.Table; import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.annotations.LazyToOne; import org.hibernate.annotations.LazyToOne;
import org.hibernate.boot.MetadataSources; import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
@ -20,11 +21,13 @@ import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions; import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
import org.hibernate.testing.jdbc.SQLStatementInterceptor; import org.hibernate.testing.jdbc.SQLStatementInterceptor;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.After; import org.junit.After;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -33,6 +36,7 @@ import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hibernate.annotations.LazyToOneOption.NO_PROXY; import static org.hibernate.annotations.LazyToOneOption.NO_PROXY;
import static org.junit.Assert.assertTrue;
/** /**
* Baseline test for inverse (mappedBy) to-one, using an explicit @LazyToOne(NO_PROXY) * Baseline test for inverse (mappedBy) to-one, using an explicit @LazyToOne(NO_PROXY)
@ -58,17 +62,6 @@ public class InverseToOneExplicitOptionTests extends BaseNonConfigCoreFunctional
@Test @Test
public void testOwnerIsProxy() { public void testOwnerIsProxy() {
inTransaction(
(session) -> {
final Customer customer = new Customer( 1, "Acme Brick" );
session.persist( customer );
final SupplementalInfo supplementalInfo = new SupplementalInfo( 1, customer, "extra details" );
session.persist( supplementalInfo );
}
);
sqlStatementInterceptor.clear();
final EntityPersister supplementalInfoDescriptor = sessionFactory().getMetamodel().entityPersister( SupplementalInfo.class ); final EntityPersister supplementalInfoDescriptor = sessionFactory().getMetamodel().entityPersister( SupplementalInfo.class );
final BytecodeEnhancementMetadata supplementalInfoEnhancementMetadata = supplementalInfoDescriptor.getBytecodeEnhancementMetadata(); final BytecodeEnhancementMetadata supplementalInfoEnhancementMetadata = supplementalInfoDescriptor.getBytecodeEnhancementMetadata();
assertThat( supplementalInfoEnhancementMetadata.isEnhancedForLazyLoading(), is( true ) ); assertThat( supplementalInfoEnhancementMetadata.isEnhancedForLazyLoading(), is( true ) );
@ -140,6 +133,40 @@ public class InverseToOneExplicitOptionTests extends BaseNonConfigCoreFunctional
); );
} }
@Test
@TestForIssue(jiraKey = "HHH-14659")
public void testQueryJoinFetch() {
SupplementalInfo info = fromTransaction( (session) -> {
final SupplementalInfo result = session.createQuery(
"select s from SupplementalInfo s join fetch s.customer",
SupplementalInfo.class )
.uniqueResult();
assertThat( sqlStatementInterceptor.getSqlQueries().size(), is( 1 ) );
return result;
} );
// The "join fetch" should have already initialized the property,
// so that the getter can safely be called outside of a session.
assertTrue( Hibernate.isPropertyInitialized( info, "customer" ) );
// The "join fetch" should have already initialized the associated entity.
Customer customer = info.getCustomer();
assertTrue( Hibernate.isInitialized( customer ) );
assertThat( sqlStatementInterceptor.getSqlQueries().size(), is( 1 ) );
}
@Before
public void createTestData() {
inTransaction(
(session) -> {
final Customer customer = new Customer( 1, "Acme Brick" );
session.persist( customer );
final SupplementalInfo supplementalInfo = new SupplementalInfo( 1, customer, "extra details" );
session.persist( supplementalInfo );
}
);
sqlStatementInterceptor.clear();
}
@After @After
public void dropTestData() { public void dropTestData() {
inTransaction( inTransaction(

View File

@ -11,6 +11,7 @@ import javax.persistence.Id;
import javax.persistence.OneToOne; import javax.persistence.OneToOne;
import javax.persistence.Table; import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.annotations.Fetch; import org.hibernate.annotations.Fetch;
import org.hibernate.boot.MetadataSources; import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
@ -21,6 +22,7 @@ import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions; import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
import org.hibernate.testing.jdbc.SQLStatementInterceptor; import org.hibernate.testing.jdbc.SQLStatementInterceptor;
@ -37,6 +39,7 @@ import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hibernate.annotations.FetchMode.JOIN; import static org.hibernate.annotations.FetchMode.JOIN;
import static org.junit.Assert.assertTrue;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -62,8 +65,6 @@ public class JoinFetchedInverseToOneAllowProxyTests extends BaseNonConfigCoreFun
@Test @Test
public void testOwnerIsProxy() { public void testOwnerIsProxy() {
sqlStatementInterceptor.clear();
final EntityPersister supplementalInfoDescriptor = sessionFactory().getMetamodel().entityPersister( SupplementalInfo.class ); final EntityPersister supplementalInfoDescriptor = sessionFactory().getMetamodel().entityPersister( SupplementalInfo.class );
final BytecodeEnhancementMetadata supplementalInfoEnhancementMetadata = supplementalInfoDescriptor.getBytecodeEnhancementMetadata(); final BytecodeEnhancementMetadata supplementalInfoEnhancementMetadata = supplementalInfoDescriptor.getBytecodeEnhancementMetadata();
assertThat( supplementalInfoEnhancementMetadata.isEnhancedForLazyLoading(), is( true ) ); assertThat( supplementalInfoEnhancementMetadata.isEnhancedForLazyLoading(), is( true ) );
@ -110,6 +111,27 @@ public class JoinFetchedInverseToOneAllowProxyTests extends BaseNonConfigCoreFun
); );
} }
@Test
@TestForIssue(jiraKey = "HHH-14659")
public void testQueryJoinFetch() {
SupplementalInfo info = fromTransaction( (session) -> {
final SupplementalInfo result = session.createQuery(
"select s from SupplementalInfo s join fetch s.customer",
SupplementalInfo.class )
.uniqueResult();
assertThat( sqlStatementInterceptor.getSqlQueries().size(), is( 1 ) );
return result;
} );
// The "join fetch" should have already initialized the property,
// so that the getter can safely be called outside of a session.
assertTrue( Hibernate.isPropertyInitialized( info, "customer" ) );
// The "join fetch" should have already initialized the associated entity.
Customer customer = info.getCustomer();
assertTrue( Hibernate.isInitialized( customer ) );
assertThat( sqlStatementInterceptor.getSqlQueries().size(), is( 1 ) );
}
@Before @Before
public void createTestData() { public void createTestData() {
inTransaction( inTransaction(
@ -120,6 +142,7 @@ public class JoinFetchedInverseToOneAllowProxyTests extends BaseNonConfigCoreFun
session.persist( supplementalInfo ); session.persist( supplementalInfo );
} }
); );
sqlStatementInterceptor.clear();
} }
@After @After

View File

@ -11,6 +11,7 @@ import javax.persistence.Id;
import javax.persistence.OneToOne; import javax.persistence.OneToOne;
import javax.persistence.Table; import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.annotations.Fetch; import org.hibernate.annotations.Fetch;
import org.hibernate.boot.MetadataSources; import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
@ -18,6 +19,7 @@ import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions; import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
import org.hibernate.testing.jdbc.SQLStatementInterceptor; import org.hibernate.testing.jdbc.SQLStatementInterceptor;
@ -31,6 +33,7 @@ import static javax.persistence.FetchType.LAZY;
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hibernate.annotations.FetchMode.JOIN; import static org.hibernate.annotations.FetchMode.JOIN;
import static org.junit.Assert.assertTrue;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -56,8 +59,6 @@ public class JoinFetchedOneToOneAllowProxyTests extends BaseNonConfigCoreFunctio
@Test @Test
public void testOwnerIsProxy() { public void testOwnerIsProxy() {
sqlStatementInterceptor.clear();
final EntityPersister supplementalInfoDescriptor = sessionFactory().getMetamodel().entityPersister( SupplementalInfo.class ); final EntityPersister supplementalInfoDescriptor = sessionFactory().getMetamodel().entityPersister( SupplementalInfo.class );
final BytecodeEnhancementMetadata supplementalInfoEnhancementMetadata = supplementalInfoDescriptor.getBytecodeEnhancementMetadata(); final BytecodeEnhancementMetadata supplementalInfoEnhancementMetadata = supplementalInfoDescriptor.getBytecodeEnhancementMetadata();
assertThat( supplementalInfoEnhancementMetadata.isEnhancedForLazyLoading(), is( true ) ); assertThat( supplementalInfoEnhancementMetadata.isEnhancedForLazyLoading(), is( true ) );
@ -94,6 +95,27 @@ public class JoinFetchedOneToOneAllowProxyTests extends BaseNonConfigCoreFunctio
); );
} }
@Test
@TestForIssue(jiraKey = "HHH-14659")
public void testQueryJoinFetch() {
SupplementalInfo info = fromTransaction( (session) -> {
final SupplementalInfo result = session.createQuery(
"select s from SupplementalInfo s join fetch s.customer",
SupplementalInfo.class )
.uniqueResult();
assertThat( sqlStatementInterceptor.getSqlQueries().size(), is( 1 ) );
return result;
} );
// The "join fetch" should have already initialized the property,
// so that the getter can safely be called outside of a session.
assertTrue( Hibernate.isPropertyInitialized( info, "customer" ) );
// The "join fetch" should have already initialized the associated entity.
Customer customer = info.getCustomer();
assertTrue( Hibernate.isInitialized( customer ) );
assertThat( sqlStatementInterceptor.getSqlQueries().size(), is( 1 ) );
}
@Before @Before
public void createTestData() { public void createTestData() {
inTransaction( inTransaction(
@ -104,6 +126,7 @@ public class JoinFetchedOneToOneAllowProxyTests extends BaseNonConfigCoreFunctio
session.persist( supplementalInfo ); session.persist( supplementalInfo );
} }
); );
sqlStatementInterceptor.clear();
} }
@After @After

View File

@ -11,6 +11,7 @@ import javax.persistence.Id;
import javax.persistence.OneToOne; import javax.persistence.OneToOne;
import javax.persistence.Table; import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.boot.MetadataSources; import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor; import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor;
@ -20,6 +21,7 @@ import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions; import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
import org.hibernate.testing.jdbc.SQLStatementInterceptor; import org.hibernate.testing.jdbc.SQLStatementInterceptor;
@ -35,6 +37,7 @@ import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertTrue;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -60,8 +63,6 @@ public class OneToOneAllowProxyTests extends BaseNonConfigCoreFunctionalTestCase
@Test @Test
public void testOwnerIsProxy() { public void testOwnerIsProxy() {
sqlStatementInterceptor.clear();
final EntityPersister supplementalInfoDescriptor = sessionFactory().getMetamodel().entityPersister( SupplementalInfo.class ); final EntityPersister supplementalInfoDescriptor = sessionFactory().getMetamodel().entityPersister( SupplementalInfo.class );
final BytecodeEnhancementMetadata supplementalInfoEnhancementMetadata = supplementalInfoDescriptor.getBytecodeEnhancementMetadata(); final BytecodeEnhancementMetadata supplementalInfoEnhancementMetadata = supplementalInfoDescriptor.getBytecodeEnhancementMetadata();
assertThat( supplementalInfoEnhancementMetadata.isEnhancedForLazyLoading(), is( true ) ); assertThat( supplementalInfoEnhancementMetadata.isEnhancedForLazyLoading(), is( true ) );
@ -114,6 +115,27 @@ public class OneToOneAllowProxyTests extends BaseNonConfigCoreFunctionalTestCase
); );
} }
@Test
@TestForIssue(jiraKey = "HHH-14659")
public void testQueryJoinFetch() {
SupplementalInfo info = fromTransaction( (session) -> {
final SupplementalInfo result = session.createQuery(
"select s from SupplementalInfo s join fetch s.customer",
SupplementalInfo.class )
.uniqueResult();
assertThat( sqlStatementInterceptor.getSqlQueries().size(), is( 1 ) );
return result;
} );
// The "join fetch" should have already initialized the property,
// so that the getter can safely be called outside of a session.
assertTrue( Hibernate.isPropertyInitialized( info, "customer" ) );
// The "join fetch" should have already initialized the associated entity.
Customer customer = info.getCustomer();
assertTrue( Hibernate.isInitialized( customer ) );
assertThat( sqlStatementInterceptor.getSqlQueries().size(), is( 1 ) );
}
@Before @Before
public void createTestData() { public void createTestData() {
inTransaction( inTransaction(
@ -124,6 +146,7 @@ public class OneToOneAllowProxyTests extends BaseNonConfigCoreFunctionalTestCase
session.persist( supplementalInfo ); session.persist( supplementalInfo );
} }
); );
sqlStatementInterceptor.clear();
} }
@After @After

View File

@ -11,6 +11,7 @@ import javax.persistence.Id;
import javax.persistence.OneToOne; import javax.persistence.OneToOne;
import javax.persistence.Table; import javax.persistence.Table;
import org.hibernate.Hibernate;
import org.hibernate.annotations.LazyToOne; import org.hibernate.annotations.LazyToOne;
import org.hibernate.boot.MetadataSources; import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
@ -21,6 +22,7 @@ import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions; import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
import org.hibernate.testing.jdbc.SQLStatementInterceptor; import org.hibernate.testing.jdbc.SQLStatementInterceptor;
@ -37,6 +39,7 @@ import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hibernate.annotations.LazyToOneOption.NO_PROXY; import static org.hibernate.annotations.LazyToOneOption.NO_PROXY;
import static org.junit.Assert.assertTrue;
/** /**
* Baseline test for uni-directional one-to-one, using an explicit @LazyToOne(NO_PROXY) and allowing enhanced proxies * Baseline test for uni-directional one-to-one, using an explicit @LazyToOne(NO_PROXY) and allowing enhanced proxies
@ -62,8 +65,6 @@ public class OneToOneExplicitOptionTests extends BaseNonConfigCoreFunctionalTest
@Test @Test
public void testOwnerIsProxy() { public void testOwnerIsProxy() {
sqlStatementInterceptor.clear();
final EntityPersister supplementalInfoDescriptor = sessionFactory().getMetamodel().entityPersister( SupplementalInfo.class ); final EntityPersister supplementalInfoDescriptor = sessionFactory().getMetamodel().entityPersister( SupplementalInfo.class );
final BytecodeEnhancementMetadata supplementalInfoEnhancementMetadata = supplementalInfoDescriptor.getBytecodeEnhancementMetadata(); final BytecodeEnhancementMetadata supplementalInfoEnhancementMetadata = supplementalInfoDescriptor.getBytecodeEnhancementMetadata();
assertThat( supplementalInfoEnhancementMetadata.isEnhancedForLazyLoading(), is( true ) ); assertThat( supplementalInfoEnhancementMetadata.isEnhancedForLazyLoading(), is( true ) );
@ -116,6 +117,27 @@ public class OneToOneExplicitOptionTests extends BaseNonConfigCoreFunctionalTest
); );
} }
@Test
@TestForIssue(jiraKey = "HHH-14659")
public void testQueryJoinFetch() {
SupplementalInfo info = fromTransaction( (session) -> {
final SupplementalInfo result = session.createQuery(
"select s from SupplementalInfo s join fetch s.customer",
SupplementalInfo.class )
.uniqueResult();
assertThat( sqlStatementInterceptor.getSqlQueries().size(), is( 1 ) );
return result;
} );
// The "join fetch" should have already initialized the property,
// so that the getter can safely be called outside of a session.
assertTrue( Hibernate.isPropertyInitialized( info, "customer" ) );
// The "join fetch" should have already initialized the associated entity.
Customer customer = info.getCustomer();
assertTrue( Hibernate.isInitialized( customer ) );
assertThat( sqlStatementInterceptor.getSqlQueries().size(), is( 1 ) );
}
@Before @Before
public void createTestData() { public void createTestData() {
inTransaction( inTransaction(
@ -126,6 +148,7 @@ public class OneToOneExplicitOptionTests extends BaseNonConfigCoreFunctionalTest
session.persist( supplementalInfo ); session.persist( supplementalInfo );
} }
); );
sqlStatementInterceptor.clear();
} }
@After @After

View File

@ -20,6 +20,7 @@ import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions; import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
import org.hibernate.testing.jdbc.SQLStatementInterceptor; import org.hibernate.testing.jdbc.SQLStatementInterceptor;
@ -72,6 +73,21 @@ public class JoinFetchedPolymorphicToOneTests extends BaseNonConfigCoreFunctiona
); );
} }
@Test
@TestForIssue(jiraKey = "HHH-14659")
public void testQueryJoinFetch() {
inTransaction(
(session) -> {
final Order order = session.createQuery( "select o from Order o join fetch o.customer", Order.class )
.uniqueResult();
assertTrue( Hibernate.isPropertyInitialized( order, "customer" ) );
Customer customer = order.getCustomer();
assertTrue( Hibernate.isInitialized( customer ) );
}
);
}
@Before @Before
public void createTestData() { public void createTestData() {
inTransaction( inTransaction(

View File

@ -22,6 +22,7 @@ import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions; import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
import org.hibernate.testing.jdbc.SQLStatementInterceptor; import org.hibernate.testing.jdbc.SQLStatementInterceptor;
@ -36,6 +37,7 @@ import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -100,6 +102,21 @@ public class PolymorphicToOneExplicitOptionTests extends BaseNonConfigCoreFuncti
); );
} }
@Test
@TestForIssue(jiraKey = "HHH-14659")
public void testQueryJoinFetch() {
inTransaction(
(session) -> {
final Order order = session.createQuery( "select o from Order o join fetch o.customer", Order.class )
.uniqueResult();
assertTrue( Hibernate.isPropertyInitialized( order, "customer" ) );
Customer customer = order.getCustomer();
assertTrue( Hibernate.isInitialized( customer ) );
}
);
}
@Before @Before
public void createTestData() { public void createTestData() {
inTransaction( inTransaction(

View File

@ -20,6 +20,7 @@ import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancementOptions; import org.hibernate.testing.bytecode.enhancement.EnhancementOptions;
import org.hibernate.testing.jdbc.SQLStatementInterceptor; import org.hibernate.testing.jdbc.SQLStatementInterceptor;
@ -34,6 +35,7 @@ import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -72,6 +74,21 @@ public class PolymorphicToOneImplicitOptionTests extends BaseNonConfigCoreFuncti
); );
} }
@Test
@TestForIssue(jiraKey = "HHH-14659")
public void testQueryJoinFetch() {
inTransaction(
(session) -> {
final Order order = session.createQuery( "select o from Order o join fetch o.customer", Order.class )
.uniqueResult();
assertTrue( Hibernate.isPropertyInitialized( order, "customer" ) );
Customer customer = order.getCustomer();
assertTrue( Hibernate.isInitialized( customer ) );
}
);
}
@Before @Before
public void createTestData() { public void createTestData() {
inTransaction( inTransaction(

View File

@ -0,0 +1,154 @@
/*
* 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.graalvm.internal;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import org.hibernate.internal.build.AllowSysOut;
import org.hibernate.internal.util.ReflectHelper;
import com.oracle.svm.core.annotate.AutomaticFeature;
import org.graalvm.nativeimage.hosted.Feature;
import org.graalvm.nativeimage.hosted.RuntimeReflection;
/**
* This registers all ANTLR parser nodes for reflection, something that is necessary
* as the HQL parser's inner workings are based on reflection.
* This is different than the "static" registrations of {@link GraalVMStaticAutofeature}
* as we only register these if the HQL parser is actually reachable: some particularly
* simple applications might not need dynamic queries being expressed in string form,
* and for such cases the reflective registrations can be skipped.
*
* At time of writing, this is particularly unlikely to be effective as Hibernate ORM
* requires the parsers during bootstrap, but there is reasonable hope that this might
* be improved on, and can already be used by framework integrations which are able
* to bypass the traditional boot sequence.
*
* @author Sanne Grinovero
*/
@AutomaticFeature
public final class QueryParsingSupport implements Feature {
private final AtomicBoolean triggered = new AtomicBoolean( false);
/**
* To set this, add `-J-Dorg.hibernate.graalvm.diagnostics=true` to the native-image parameters
*/
private static final boolean log = Boolean.getBoolean( "org.hibernate.graalvm.diagnostics" );
@Override
public void beforeAnalysis(BeforeAnalysisAccess access) {
Class<?> lexerClazz = access.findClassByName("org.hibernate.grammars.hql.HqlLexer");
Class<?> parserClazz = access.findClassByName("org.hibernate.grammars.hql.HqlParser");
access.registerReachabilityHandler(this::enableHQLSupport, lexerClazz);
access.registerReachabilityHandler(this::enableHQLSupport, parserClazz);
}
@AllowSysOut
private void enableHQLSupport(DuringAnalysisAccess duringAnalysisAccess) {
final boolean needsEnablingYet = triggered.compareAndSet( false, true );
if ( needsEnablingYet ) {
if ( log ) {
System.out.println( "Hibernate ORM 's automatic feature for GraalVM native images: enabling support for HQL query parsing" );
}
enableAntlrParsersSupport();
}
}
private void enableAntlrParsersSupport() {
final Class<?>[] needsHavingSimpleConstructors = typesNeedingDefaultConstructorAccessible();
final Class[] neddingAllConstructorsAccessible = typesNeedingAllConstructorsAccessible();
//Size formula is just a reasonable guess:
ArrayList<Executable> executables = new ArrayList<>( needsHavingSimpleConstructors.length + neddingAllConstructorsAccessible.length * 3 );
for ( Class c : needsHavingSimpleConstructors ) {
executables.add( ReflectHelper.getDefaultConstructor( c ) );
}
for ( Class c : neddingAllConstructorsAccessible ) {
for ( Constructor declaredConstructor : c.getDeclaredConstructors() ) {
executables.add( declaredConstructor );
}
}
RuntimeReflection.register( needsHavingSimpleConstructors );
RuntimeReflection.register( neddingAllConstructorsAccessible );
RuntimeReflection.register( executables.toArray(new Executable[0]) );
}
public static Class[] typesNeedingAllConstructorsAccessible() {
return new Class[] {
//ANTLR special ones:
// org.hibernate.hql.internal.ast.tree.EntityJoinFromElement.class,
// org.hibernate.hql.internal.ast.tree.MapKeyEntityFromElement.class,
// org.hibernate.hql.internal.ast.tree.ComponentJoin.class,
};
}
public static Class[] typesNeedingDefaultConstructorAccessible() {
return new Class[] {
//Support for @OrderBy
// org.hibernate.sql.ordering.antlr.NodeSupport.class,
// org.hibernate.sql.ordering.antlr.OrderByFragment.class,
// org.hibernate.sql.ordering.antlr.SortSpecification.class,
// org.hibernate.sql.ordering.antlr.OrderingSpecification.class,
// org.hibernate.sql.ordering.antlr.CollationSpecification.class,
// org.hibernate.sql.ordering.antlr.SortKey.class,
//ANTLR tokens:
// antlr.CommonToken.class,
// org.hibernate.hql.internal.ast.tree.SelectClause.class,
// org.hibernate.hql.internal.ast.tree.HqlSqlWalkerNode.class,
// org.hibernate.hql.internal.ast.tree.MethodNode.class,
// org.hibernate.hql.internal.ast.tree.UnaryLogicOperatorNode.class,
// org.hibernate.hql.internal.ast.tree.NullNode.class,
// org.hibernate.hql.internal.ast.tree.IntoClause.class,
// org.hibernate.hql.internal.ast.tree.UpdateStatement.class,
// org.hibernate.hql.internal.ast.tree.SelectExpressionImpl.class,
// org.hibernate.hql.internal.ast.tree.CastFunctionNode.class,
// org.hibernate.hql.internal.ast.tree.DeleteStatement.class,
// org.hibernate.hql.internal.ast.tree.SqlNode.class,
// org.hibernate.hql.internal.ast.tree.SearchedCaseNode.class,
// org.hibernate.hql.internal.ast.tree.FromElement.class,
// org.hibernate.hql.internal.ast.tree.JavaConstantNode.class,
// org.hibernate.hql.internal.ast.tree.SqlFragment.class,
// org.hibernate.hql.internal.ast.tree.MapKeyNode.class,
// org.hibernate.hql.internal.ast.tree.ImpliedFromElement.class,
// org.hibernate.hql.internal.ast.tree.IsNotNullLogicOperatorNode.class,
// org.hibernate.hql.internal.ast.tree.InsertStatement.class,
// org.hibernate.hql.internal.ast.tree.UnaryArithmeticNode.class,
// org.hibernate.hql.internal.ast.tree.CollectionFunction.class,
// org.hibernate.hql.internal.ast.tree.BinaryLogicOperatorNode.class,
// org.hibernate.hql.internal.ast.tree.CountNode.class,
// org.hibernate.hql.internal.ast.tree.IsNullLogicOperatorNode.class,
// org.hibernate.hql.internal.ast.tree.IdentNode.class,
// org.hibernate.hql.internal.ast.tree.ParameterNode.class,
// org.hibernate.hql.internal.ast.tree.MapEntryNode.class,
// org.hibernate.hql.internal.ast.tree.MapValueNode.class,
// org.hibernate.hql.internal.ast.tree.InLogicOperatorNode.class,
// org.hibernate.hql.internal.ast.tree.IndexNode.class,
// org.hibernate.hql.internal.ast.tree.DotNode.class,
// org.hibernate.hql.internal.ast.tree.ResultVariableRefNode.class,
// org.hibernate.hql.internal.ast.tree.BetweenOperatorNode.class,
// org.hibernate.hql.internal.ast.tree.AggregateNode.class,
// org.hibernate.hql.internal.ast.tree.QueryNode.class,
// org.hibernate.hql.internal.ast.tree.BooleanLiteralNode.class,
// org.hibernate.hql.internal.ast.tree.SimpleCaseNode.class,
// org.hibernate.hql.internal.ast.tree.OrderByClause.class,
// org.hibernate.hql.internal.ast.tree.FromClause.class,
// org.hibernate.hql.internal.ast.tree.ConstructorNode.class,
// org.hibernate.hql.internal.ast.tree.LiteralNode.class,
// org.hibernate.hql.internal.ast.tree.BinaryArithmeticOperatorNode.class,
//Special tokens:
// org.hibernate.hql.internal.ast.HqlToken.class,
// org.hibernate.hql.internal.ast.tree.Node.class,
};
}
}

View File

@ -31,78 +31,18 @@ final class StaticClassLists {
org.hibernate.persister.entity.UnionSubclassEntityPersister.class, org.hibernate.persister.entity.UnionSubclassEntityPersister.class,
org.hibernate.persister.entity.SingleTableEntityPersister.class, org.hibernate.persister.entity.SingleTableEntityPersister.class,
org.hibernate.tuple.entity.PojoEntityTuplizer.class, org.hibernate.tuple.entity.PojoEntityTuplizer.class,
//ANTLR special ones:
// org.hibernate.hql.internal.ast.tree.EntityJoinFromElement.class,
// org.hibernate.hql.internal.ast.tree.MapKeyEntityFromElement.class,
// org.hibernate.hql.internal.ast.tree.ComponentJoin.class,
}; };
} }
public static Class[] typesNeedingDefaultConstructorAccessible() { public static Class[] typesNeedingDefaultConstructorAccessible() {
return new Class[] { return new Class[] {
//Support for @OrderBy
// org.hibernate.sql.ordering.antlr.NodeSupport.class,
// org.hibernate.sql.ordering.antlr.OrderByFragment.class,
// org.hibernate.sql.ordering.antlr.SortSpecification.class,
// org.hibernate.sql.ordering.antlr.OrderingSpecification.class,
// org.hibernate.sql.ordering.antlr.CollationSpecification.class,
// org.hibernate.sql.ordering.antlr.SortKey.class,
//ANTLR tokens:
// antlr.CommonToken.class,
// org.hibernate.hql.internal.ast.tree.SelectClause.class,
// org.hibernate.hql.internal.ast.tree.HqlSqlWalkerNode.class,
// org.hibernate.hql.internal.ast.tree.MethodNode.class,
// org.hibernate.hql.internal.ast.tree.UnaryLogicOperatorNode.class,
// org.hibernate.hql.internal.ast.tree.NullNode.class,
// org.hibernate.hql.internal.ast.tree.IntoClause.class,
// org.hibernate.hql.internal.ast.tree.UpdateStatement.class,
// org.hibernate.hql.internal.ast.tree.SelectExpressionImpl.class,
// org.hibernate.hql.internal.ast.tree.CastFunctionNode.class,
// org.hibernate.hql.internal.ast.tree.DeleteStatement.class,
// org.hibernate.hql.internal.ast.tree.SqlNode.class,
// org.hibernate.hql.internal.ast.tree.SearchedCaseNode.class,
// org.hibernate.hql.internal.ast.tree.FromElement.class,
// org.hibernate.hql.internal.ast.tree.JavaConstantNode.class,
// org.hibernate.hql.internal.ast.tree.SqlFragment.class,
// org.hibernate.hql.internal.ast.tree.MapKeyNode.class,
// org.hibernate.hql.internal.ast.tree.ImpliedFromElement.class,
// org.hibernate.hql.internal.ast.tree.IsNotNullLogicOperatorNode.class,
// org.hibernate.hql.internal.ast.tree.InsertStatement.class,
// org.hibernate.hql.internal.ast.tree.UnaryArithmeticNode.class,
// org.hibernate.hql.internal.ast.tree.CollectionFunction.class,
// org.hibernate.hql.internal.ast.tree.BinaryLogicOperatorNode.class,
// org.hibernate.hql.internal.ast.tree.CountNode.class,
// org.hibernate.hql.internal.ast.tree.IsNullLogicOperatorNode.class,
// org.hibernate.hql.internal.ast.tree.IdentNode.class,
// org.hibernate.hql.internal.ast.tree.ParameterNode.class,
// org.hibernate.hql.internal.ast.tree.MapEntryNode.class,
// org.hibernate.hql.internal.ast.tree.MapValueNode.class,
// org.hibernate.hql.internal.ast.tree.InLogicOperatorNode.class,
// org.hibernate.hql.internal.ast.tree.IndexNode.class,
// org.hibernate.hql.internal.ast.tree.DotNode.class,
// org.hibernate.hql.internal.ast.tree.ResultVariableRefNode.class,
// org.hibernate.hql.internal.ast.tree.BetweenOperatorNode.class,
// org.hibernate.hql.internal.ast.tree.AggregateNode.class,
// org.hibernate.hql.internal.ast.tree.QueryNode.class,
// org.hibernate.hql.internal.ast.tree.BooleanLiteralNode.class,
// org.hibernate.hql.internal.ast.tree.SimpleCaseNode.class,
// org.hibernate.hql.internal.ast.tree.OrderByClause.class,
// org.hibernate.hql.internal.ast.tree.FromClause.class,
// org.hibernate.hql.internal.ast.tree.ConstructorNode.class,
// org.hibernate.hql.internal.ast.tree.LiteralNode.class,
// org.hibernate.hql.internal.ast.tree.BinaryArithmeticOperatorNode.class,
//Various well known needs: //Various well known needs:
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorBuilderImpl.class, org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorBuilderImpl.class,
org.hibernate.id.enhanced.SequenceStyleGenerator.class, org.hibernate.id.enhanced.SequenceStyleGenerator.class,
org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl.class, org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl.class,
org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorBuilderImpl.class, org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorBuilderImpl.class,
EnumType.class, EnumType.class,
MultipleLinesSqlCommandExtractor.class, MultipleLinesSqlCommandExtractor.class,
// org.hibernate.hql.internal.ast.HqlToken.class,
// org.hibernate.hql.internal.ast.tree.Node.class,
}; };
} }