Skip to content

Commit

Permalink
Merge pull request #7826 from Sanne/enums
Browse files Browse the repository at this point in the history
Hibernate ORM: further move some metadata validation and processing to Augmentation
  • Loading branch information
gsmet authored Mar 12, 2020
2 parents e0419cb + ae12f4b commit 2c39bce
Show file tree
Hide file tree
Showing 8 changed files with 323 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder;
import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
Expand All @@ -27,6 +26,7 @@
import io.quarkus.hibernate.orm.runtime.boot.FastBootEntityManagerFactoryBuilder;
import io.quarkus.hibernate.orm.runtime.boot.registry.PreconfiguredServiceRegistryBuilder;
import io.quarkus.hibernate.orm.runtime.integration.HibernateOrmIntegrations;
import io.quarkus.hibernate.orm.runtime.recording.PrevalidatedQuarkusMetadata;
import io.quarkus.hibernate.orm.runtime.recording.RecordedState;

/**
Expand Down Expand Up @@ -145,7 +145,7 @@ private EntityManagerFactoryBuilder getEntityManagerFactoryBuilderOrNull(String

RecordedState recordedState = PersistenceUnitsHolder.getRecordedState(persistenceUnitName);

final MetadataImplementor metadata = recordedState.getMetadata();
final PrevalidatedQuarkusMetadata metadata = recordedState.getMetadata();
final BuildTimeSettings buildTimeSettings = recordedState.getBuildTimeSettings();
final IntegrationSettings integrationSettings = recordedState.getIntegrationSettings();
RuntimeSettings.Builder runtimeSettingsBuilder = new RuntimeSettings.Builder(buildTimeSettings,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@

import org.hibernate.SessionFactory;
import org.hibernate.SessionFactoryObserver;
import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.internal.SessionFactoryOptionsBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.boot.spi.SessionFactoryBuilderImplementor;
import org.hibernate.bytecode.internal.SessionFactoryObserverForBytecodeEnhancer;
import org.hibernate.bytecode.spi.BytecodeProvider;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.jpa.AvailableSettings;
import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder;
import org.hibernate.proxy.EntityNotFoundDelegate;
Expand All @@ -26,17 +27,19 @@
import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator;

import io.quarkus.hibernate.orm.runtime.RuntimeSettings;
import io.quarkus.hibernate.orm.runtime.recording.PrevalidatedQuarkusMetadata;

public final class FastBootEntityManagerFactoryBuilder implements EntityManagerFactoryBuilder {

private final MetadataImplementor metadata;
private final PrevalidatedQuarkusMetadata metadata;
private final String persistenceUnitName;
private final StandardServiceRegistry standardServiceRegistry;
private final RuntimeSettings runtimeSettings;
private final Object validatorFactory;
private final Object cdiBeanManager;

public FastBootEntityManagerFactoryBuilder(MetadataImplementor metadata, String persistenceUnitName,
public FastBootEntityManagerFactoryBuilder(
PrevalidatedQuarkusMetadata metadata, String persistenceUnitName,
StandardServiceRegistry standardServiceRegistry, RuntimeSettings runtimeSettings, Object validatorFactory,
Object cdiBeanManager) {
this.metadata = metadata;
Expand All @@ -59,10 +62,10 @@ public EntityManagerFactoryBuilder withDataSource(DataSource dataSource) {

@Override
public EntityManagerFactory build() {
SessionFactoryBuilder sfBuilder = metadata.getSessionFactoryBuilder();
populate(sfBuilder, standardServiceRegistry);
try {
return sfBuilder.build();
final SessionFactoryOptionsBuilder optionsBuilder = metadata.buildSessionFactoryOptionsBuilder();
populate(optionsBuilder, standardServiceRegistry);
return new SessionFactoryImpl(metadata.getOriginalMetadata(), optionsBuilder.buildOptions());
} catch (Exception e) {
throw persistenceException("Unable to build Hibernate SessionFactory", e);
}
Expand All @@ -75,13 +78,7 @@ public void cancel() {

@Override
public void generateSchema() {
// This seems overkill, but building the SF is necessary to get the Integrators
// to kick in.
// Metamodel will clean this up...
try {
SessionFactoryBuilder sfBuilder = metadata.getSessionFactoryBuilder();
populate(sfBuilder, standardServiceRegistry);

SchemaManagementToolCoordinator.process(metadata, standardServiceRegistry, runtimeSettings.getSettings(),
DelayedDropRegistryNotAvailableImpl.INSTANCE);
} catch (Exception e) {
Expand Down Expand Up @@ -117,20 +114,20 @@ private String getExceptionHeader() {
return "[PersistenceUnit: " + persistenceUnitName + "] ";
}

protected void populate(SessionFactoryBuilder sfBuilder, StandardServiceRegistry ssr) {
protected void populate(SessionFactoryOptionsBuilder options, StandardServiceRegistry ssr) {

// will use user override value or default to false if not supplied to follow
// JPA spec.
final boolean jtaTransactionAccessEnabled = runtimeSettings.getBoolean(
AvailableSettings.ALLOW_JTA_TRANSACTION_ACCESS);
if (!jtaTransactionAccessEnabled) {
((SessionFactoryBuilderImplementor) sfBuilder).disableJtaTransactionAccess();
options.disableJtaTransactionAccess();
}

final boolean allowRefreshDetachedEntity = runtimeSettings.getBoolean(
org.hibernate.cfg.AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY);
if (!allowRefreshDetachedEntity) {
((SessionFactoryBuilderImplementor) sfBuilder).disableRefreshDetachedEntity();
options.disableRefreshDetachedEntity();
}

// Locate and apply any requested SessionFactoryObserver
Expand All @@ -140,19 +137,25 @@ protected void populate(SessionFactoryBuilder sfBuilder, StandardServiceRegistry
final StrategySelector strategySelector = ssr.getService(StrategySelector.class);
final SessionFactoryObserver suppliedSessionFactoryObserver = strategySelector
.resolveStrategy(SessionFactoryObserver.class, sessionFactoryObserverSetting);
sfBuilder.addSessionFactoryObservers(suppliedSessionFactoryObserver);
options.addSessionFactoryObservers(suppliedSessionFactoryObserver);
}

sfBuilder.addSessionFactoryObservers(new ServiceRegistryCloser());
options.addSessionFactoryObservers(new ServiceRegistryCloser());

sfBuilder.applyEntityNotFoundDelegate(new JpaEntityNotFoundDelegate());
options.applyEntityNotFoundDelegate(new JpaEntityNotFoundDelegate());

if (this.validatorFactory != null) {
sfBuilder.applyValidatorFactory(validatorFactory);
options.applyValidatorFactory(validatorFactory);
}
if (this.cdiBeanManager != null) {
sfBuilder.applyBeanManager(cdiBeanManager);
options.applyBeanManager(cdiBeanManager);
}

//Small memory optimisations: ensure the class transformation caches of the bytecode enhancer
//are cleared both on start and on close of the SessionFactory.
//(On start is useful especially in Quarkus as we won't do any more enhancement after this point)
BytecodeProvider bytecodeProvider = ssr.getService(BytecodeProvider.class);
options.addSessionFactoryObservers(new SessionFactoryObserverForBytecodeEnhancer(bytecodeProvider));
}

private static class ServiceRegistryCloser implements SessionFactoryObserver {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
import io.quarkus.hibernate.orm.runtime.customized.QuarkusJtaPlatform;
import io.quarkus.hibernate.orm.runtime.integration.HibernateOrmIntegrations;
import io.quarkus.hibernate.orm.runtime.proxies.ProxyDefinitions;
import io.quarkus.hibernate.orm.runtime.recording.PrevalidatedQuarkusMetadata;
import io.quarkus.hibernate.orm.runtime.recording.RecordableBootstrap;
import io.quarkus.hibernate.orm.runtime.recording.RecordedState;
import io.quarkus.hibernate.orm.runtime.recording.RecordingDialectFactory;
Expand Down Expand Up @@ -333,8 +334,9 @@ public RecordedState build() {

Dialect dialect = extractDialect();
JtaPlatform jtaPlatform = extractJtaPlatform();
PrevalidatedQuarkusMetadata storeableMetadata = trimBootstrapMetadata(fullMeta);
//Make sure that the service is destroyed after the metadata has been validated and trimmed, as validation needs to use it.
destroyServiceRegistry(fullMeta);
MetadataImplementor storeableMetadata = trimBootstrapMetadata(fullMeta);
ProxyDefinitions proxyClassDefinitions = ProxyDefinitions.createFromMetadata(storeableMetadata);
return new RecordedState(dialect, jtaPlatform, storeableMetadata, buildTimeSettings, getIntegrators(),
providedServices, integrationSettingsBuilder.build(), proxyClassDefinitions);
Expand All @@ -347,7 +349,7 @@ private void destroyServiceRegistry(MetadataImplementor fullMeta) {
serviceRegistry.resetParent(null);
}

private MetadataImplementor trimBootstrapMetadata(MetadataImpl fullMeta) {
private PrevalidatedQuarkusMetadata trimBootstrapMetadata(MetadataImpl fullMeta) {
MetadataImpl replacement = new MetadataImpl(
fullMeta.getUUID(),
fullMeta.getMetadataBuildingOptions(), //TODO Replace this
Expand All @@ -370,7 +372,7 @@ private MetadataImplementor trimBootstrapMetadata(MetadataImpl fullMeta) {
fullMeta.getBootstrapContext() //FIXME WHOA!
);

return replacement;
return PrevalidatedQuarkusMetadata.validateAndWrap(replacement);
}

private JtaPlatform extractJtaPlatform() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ public class PreconfiguredServiceRegistryBuilder {
public PreconfiguredServiceRegistryBuilder(RecordedState rs) {
this.initiators = buildQuarkusServiceInitiatorList(rs);
this.integrators = rs.getIntegrators();
this.destroyedRegistry = (StandardServiceRegistryImpl) rs.getMetadata().getMetadataBuildingOptions()
this.destroyedRegistry = (StandardServiceRegistryImpl) rs.getMetadata().getOriginalMetadata()
.getMetadataBuildingOptions()
.getServiceRegistry();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import java.util.Set;

import org.hibernate.HibernateException;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.boot.Metadata;
import org.hibernate.bytecode.internal.bytebuddy.BytecodeProviderImpl;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
Expand Down Expand Up @@ -49,7 +49,7 @@ private ProxyDefinitions(Map<Class<?>, ProxyClassDetailsHolder> proxyDefinitionM
this.proxyDefinitionMap = proxyDefinitionMap;
}

public static ProxyDefinitions createFromMetadata(MetadataImplementor storeableMetadata) {
public static ProxyDefinitions createFromMetadata(Metadata storeableMetadata) {
//Check upfront for any need across all metadata: would be nice to avoid initializing the Bytecode provider.
if (needAnyProxyDefinitions(storeableMetadata)) {
final HashMap<Class<?>, ProxyClassDetailsHolder> proxyDefinitionMap = new HashMap<>();
Expand Down Expand Up @@ -83,7 +83,7 @@ public static ProxyDefinitions createFromMetadata(MetadataImplementor storeableM
}
}

private static boolean needAnyProxyDefinitions(MetadataImplementor storeableMetadata) {
private static boolean needAnyProxyDefinitions(Metadata storeableMetadata) {
for (PersistentClass persistentClass : storeableMetadata.getEntityBindings()) {
if (needsProxyGeneration(persistentClass))
return true;
Expand Down
Loading

0 comments on commit 2c39bce

Please sign in to comment.