fixed source of NPE wrt accessing an entity's version attribute descriptor when no versioning is defined;
added `@org.hibernate.testing.orm.junit.SessionFactory#exportSchema`
This commit is contained in:
parent
12ca8a2a81
commit
b9f4562680
|
@ -141,10 +141,10 @@ import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
import org.hibernate.metamodel.mapping.NaturalIdMapping;
|
import org.hibernate.metamodel.mapping.NaturalIdMapping;
|
||||||
import org.hibernate.metamodel.mapping.Queryable;
|
import org.hibernate.metamodel.mapping.Queryable;
|
||||||
import org.hibernate.metamodel.mapping.StateArrayContributorMapping;
|
import org.hibernate.metamodel.mapping.StateArrayContributorMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.StateArrayContributorMetadata;
|
||||||
import org.hibernate.metamodel.mapping.internal.InFlightEntityMappingType;
|
import org.hibernate.metamodel.mapping.internal.InFlightEntityMappingType;
|
||||||
import org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper;
|
import org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper;
|
||||||
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
|
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
|
||||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||||
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
|
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
|
||||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||||
|
@ -159,10 +159,7 @@ import org.hibernate.property.access.spi.PropertyAccess;
|
||||||
import org.hibernate.property.access.spi.Setter;
|
import org.hibernate.property.access.spi.Setter;
|
||||||
import org.hibernate.query.ComparisonOperator;
|
import org.hibernate.query.ComparisonOperator;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.query.sqm.SqmPathSource;
|
|
||||||
import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
|
||||||
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
|
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
|
||||||
import org.hibernate.sql.Alias;
|
import org.hibernate.sql.Alias;
|
||||||
import org.hibernate.sql.Delete;
|
import org.hibernate.sql.Delete;
|
||||||
import org.hibernate.sql.Insert;
|
import org.hibernate.sql.Insert;
|
||||||
|
@ -174,7 +171,6 @@ import org.hibernate.sql.SimpleSelect;
|
||||||
import org.hibernate.sql.Template;
|
import org.hibernate.sql.Template;
|
||||||
import org.hibernate.sql.Update;
|
import org.hibernate.sql.Update;
|
||||||
import org.hibernate.sql.ast.Clause;
|
import org.hibernate.sql.ast.Clause;
|
||||||
import org.hibernate.sql.ast.spi.FromClauseAccess;
|
|
||||||
import org.hibernate.sql.ast.spi.SqlAliasBase;
|
import org.hibernate.sql.ast.spi.SqlAliasBase;
|
||||||
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
|
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
|
||||||
import org.hibernate.sql.ast.spi.SqlAliasStemHelper;
|
import org.hibernate.sql.ast.spi.SqlAliasStemHelper;
|
||||||
|
@ -5357,7 +5353,12 @@ public abstract class AbstractEntityPersister
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getVersion(Object object) {
|
public Object getVersion(Object object) {
|
||||||
return getVersionMapping().getAttributeMetadataAccess().resolveAttributeMetadata( this ).getPropertyAccess().getGetter().get( object );
|
if ( getVersionMapping() == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final StateArrayContributorMetadata attrMetadata = getVersionMapping().getAttributeMetadataAccess().resolveAttributeMetadata( this );
|
||||||
|
assert attrMetadata != null;
|
||||||
|
return attrMetadata.getPropertyAccess().getGetter().get( object );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* 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.loading;
|
||||||
|
|
||||||
|
import org.hibernate.Hibernate;
|
||||||
|
import org.hibernate.boot.MetadataSources;
|
||||||
|
import org.hibernate.query.spi.QueryImplementor;
|
||||||
|
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.hibernate.testing.orm.domain.StandardDomainModel;
|
||||||
|
import org.hibernate.testing.orm.domain.gambit.BasicEntity;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.FailureExpected;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryFunctionalTesting;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.hamcrest.MatcherAssert;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@DomainModel(
|
||||||
|
standardModels = StandardDomainModel.GAMBIT
|
||||||
|
)
|
||||||
|
@SessionFactory
|
||||||
|
@SessionFactoryFunctionalTesting
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
public class LoadingSmokeTests {
|
||||||
|
@Test
|
||||||
|
public void testBasicLoad(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
final BasicEntity loaded = session.byId( BasicEntity.class ).getReference( 1 );
|
||||||
|
assertThat( loaded, notNullValue() );
|
||||||
|
assertFalse( Hibernate.isInitialized( loaded ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@FailureExpected( reason = "read-by-position not yet implemented for loading" )
|
||||||
|
public void testBasicGet(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
final BasicEntity gotten = session.byId( BasicEntity.class ).load( 1 );
|
||||||
|
assertThat( gotten, notNullValue() );
|
||||||
|
assertTrue( Hibernate.isInitialized( gotten ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
public void createTestData(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.persist( new BasicEntity( 1, "first" ) );
|
||||||
|
session.persist( new BasicEntity( 2, "second" ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public void deleteTestData(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.doWork(
|
||||||
|
connection -> {
|
||||||
|
connection.prepareStatement( "delete from BasicEntity" ).execute();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,7 +32,7 @@ public class DomainModelExtension
|
||||||
return JUnitHelper.locateExtensionStore( ServiceRegistryExtension.class, context, testInstance );
|
return JUnitHelper.locateExtensionStore( ServiceRegistryExtension.class, context, testInstance );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DomainModelScope findMetamodelScope(Object testInstance, ExtensionContext context) {
|
public static DomainModelScope findDomainModelScope(Object testInstance, ExtensionContext context) {
|
||||||
final ExtensionContext.Store store = locateExtensionStore( testInstance, context );
|
final ExtensionContext.Store store = locateExtensionStore( testInstance, context );
|
||||||
final DomainModelScope existing = (DomainModelScope) store.get( MODEL_KEY );
|
final DomainModelScope existing = (DomainModelScope) store.get( MODEL_KEY );
|
||||||
if ( existing != null ) {
|
if ( existing != null ) {
|
||||||
|
@ -120,7 +120,7 @@ public class DomainModelExtension
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postProcessTestInstance(Object testInstance, ExtensionContext context) {
|
public void postProcessTestInstance(Object testInstance, ExtensionContext context) {
|
||||||
findMetamodelScope( testInstance, context );
|
findDomainModelScope( testInstance, context );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -28,7 +28,7 @@ public class DomainModelParameterResolver implements ParameterResolver {
|
||||||
public Object resolveParameter(
|
public Object resolveParameter(
|
||||||
ParameterContext parameterContext,
|
ParameterContext parameterContext,
|
||||||
ExtensionContext extensionContext) throws ParameterResolutionException {
|
ExtensionContext extensionContext) throws ParameterResolutionException {
|
||||||
final DomainModelScope modelScope = DomainModelExtension.findMetamodelScope(
|
final DomainModelScope modelScope = DomainModelExtension.findDomainModelScope(
|
||||||
extensionContext.getRequiredTestInstance(),
|
extensionContext.getRequiredTestInstance(),
|
||||||
extensionContext
|
extensionContext
|
||||||
);
|
);
|
||||||
|
|
|
@ -42,6 +42,7 @@ public @interface SessionFactory {
|
||||||
String sessionFactoryName() default "";
|
String sessionFactoryName() default "";
|
||||||
|
|
||||||
boolean generateStatistics() default false;
|
boolean generateStatistics() default false;
|
||||||
|
boolean exportSchema() default true;
|
||||||
|
|
||||||
Class<? extends Interceptor> interceptorClass() default Interceptor.class;
|
Class<? extends Interceptor> interceptorClass() default Interceptor.class;
|
||||||
|
|
||||||
|
|
|
@ -6,17 +6,26 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.testing.orm.junit;
|
package org.hibernate.testing.orm.junit;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.hibernate.Interceptor;
|
import org.hibernate.Interceptor;
|
||||||
|
import org.hibernate.SessionFactoryObserver;
|
||||||
import org.hibernate.Transaction;
|
import org.hibernate.Transaction;
|
||||||
import org.hibernate.boot.SessionFactoryBuilder;
|
import org.hibernate.boot.SessionFactoryBuilder;
|
||||||
|
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||||
|
import org.hibernate.boot.spi.MetadataImplementor;
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SessionImplementor;
|
import org.hibernate.engine.spi.SessionImplementor;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.resource.jdbc.spi.StatementInspector;
|
import org.hibernate.resource.jdbc.spi.StatementInspector;
|
||||||
|
import org.hibernate.tool.schema.Action;
|
||||||
|
import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator;
|
||||||
|
import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.ActionGrouping;
|
||||||
|
|
||||||
import org.junit.jupiter.api.extension.AfterAllCallback;
|
import org.junit.jupiter.api.extension.AfterAllCallback;
|
||||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||||
|
@ -49,6 +58,8 @@ public class SessionFactoryExtension
|
||||||
|
|
||||||
SessionFactoryProducer producer = null;
|
SessionFactoryProducer producer = null;
|
||||||
|
|
||||||
|
final DomainModelScope domainModelScope = DomainModelExtension.findDomainModelScope( testInstance, context );
|
||||||
|
|
||||||
if ( testInstance instanceof SessionFactoryProducer ) {
|
if ( testInstance instanceof SessionFactoryProducer ) {
|
||||||
producer = (SessionFactoryProducer) testInstance;
|
producer = (SessionFactoryProducer) testInstance;
|
||||||
}
|
}
|
||||||
|
@ -85,7 +96,13 @@ public class SessionFactoryExtension
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (SessionFactoryImplementor) sessionFactoryBuilder.build();
|
final SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) sessionFactoryBuilder.build();
|
||||||
|
|
||||||
|
if ( sessionFactoryConfig.exportSchema() ) {
|
||||||
|
prepareSchemaExport( sessionFactory, model );
|
||||||
|
}
|
||||||
|
|
||||||
|
return sessionFactory;
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
throw new RuntimeException( "Could not build SessionFactory", e );
|
throw new RuntimeException( "Could not build SessionFactory", e );
|
||||||
|
@ -98,9 +115,8 @@ public class SessionFactoryExtension
|
||||||
throw new IllegalStateException( "Could not determine SessionFactory producer" );
|
throw new IllegalStateException( "Could not determine SessionFactory producer" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
final SessionFactoryScopeImpl sfScope = new SessionFactoryScopeImpl(
|
final SessionFactoryScopeImpl sfScope = new SessionFactoryScopeImpl(
|
||||||
DomainModelExtension.findMetamodelScope( testInstance, context ),
|
domainModelScope,
|
||||||
producer
|
producer
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -113,6 +129,40 @@ public class SessionFactoryExtension
|
||||||
return sfScope;
|
return sfScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void prepareSchemaExport(
|
||||||
|
SessionFactoryImplementor sessionFactory,
|
||||||
|
MetadataImplementor model) {
|
||||||
|
final Map<String, Object> baseProperties = sessionFactory.getProperties();
|
||||||
|
|
||||||
|
final ActionGrouping actions = ActionGrouping.interpret( baseProperties );
|
||||||
|
|
||||||
|
// if there are explicit setting for auto schema tooling then skip the annotation
|
||||||
|
if ( actions.getDatabaseAction() != Action.NONE || actions.getScriptAction() != Action.NONE ) {
|
||||||
|
// the properties contained explicit settings for auto schema tooling - skip the annotation
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final HashMap settings = new HashMap<>( baseProperties );
|
||||||
|
//noinspection unchecked
|
||||||
|
settings.put( AvailableSettings.HBM2DDL_DATABASE_ACTION, Action.CREATE_DROP );
|
||||||
|
|
||||||
|
final StandardServiceRegistry serviceRegistry = model.getMetadataBuildingOptions().getServiceRegistry();
|
||||||
|
|
||||||
|
SchemaManagementToolCoordinator.process(
|
||||||
|
model,
|
||||||
|
serviceRegistry,
|
||||||
|
settings,
|
||||||
|
action -> sessionFactory.addObserver(
|
||||||
|
new SessionFactoryObserver() {
|
||||||
|
@Override
|
||||||
|
public void sessionFactoryClosing(org.hibernate.SessionFactory factory) {
|
||||||
|
action.perform( serviceRegistry );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postProcessTestInstance(Object testInstance, ExtensionContext context) {
|
public void postProcessTestInstance(Object testInstance, ExtensionContext context) {
|
||||||
log.tracef( "#postProcessTestInstance(%s, %s)", testInstance, context.getDisplayName() );
|
log.tracef( "#postProcessTestInstance(%s, %s)", testInstance, context.getDisplayName() );
|
||||||
|
|
Loading…
Reference in New Issue