HHH-13015 Optimise loading of EntityCopyObserver implementation
This commit is contained in:
parent
415fcfd048
commit
cced0ad568
|
@ -166,7 +166,6 @@ public class StrategySelectorBuilder {
|
|||
addJtaPlatforms( strategySelector );
|
||||
addTransactionCoordinatorBuilders( strategySelector );
|
||||
addMultiTableBulkIdStrategies( strategySelector );
|
||||
addEntityCopyObserverStrategies( strategySelector );
|
||||
addImplicitNamingStrategies( strategySelector );
|
||||
addCacheKeysFactories( strategySelector );
|
||||
|
||||
|
@ -429,24 +428,6 @@ public class StrategySelectorBuilder {
|
|||
);
|
||||
}
|
||||
|
||||
private void addEntityCopyObserverStrategies(StrategySelectorImpl strategySelector) {
|
||||
strategySelector.registerStrategyImplementor(
|
||||
EntityCopyObserver.class,
|
||||
EntityCopyNotAllowedObserver.SHORT_NAME,
|
||||
EntityCopyNotAllowedObserver.class
|
||||
);
|
||||
strategySelector.registerStrategyImplementor(
|
||||
EntityCopyObserver.class,
|
||||
EntityCopyAllowedObserver.SHORT_NAME,
|
||||
EntityCopyAllowedObserver.class
|
||||
);
|
||||
strategySelector.registerStrategyImplementor(
|
||||
EntityCopyObserver.class,
|
||||
EntityCopyAllowedLoggedObserver.SHORT_NAME,
|
||||
EntityCopyAllowedLoggedObserver.class
|
||||
);
|
||||
}
|
||||
|
||||
private void addImplicitNamingStrategies(StrategySelectorImpl strategySelector) {
|
||||
strategySelector.registerStrategyImplementor(
|
||||
ImplicitNamingStrategy.class,
|
||||
|
|
|
@ -14,9 +14,6 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.ObjectDeletedException;
|
||||
import org.hibernate.StaleObjectStateException;
|
||||
import org.hibernate.WrongClassException;
|
||||
import org.hibernate.boot.registry.selector.spi.StrategySelector;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
import org.hibernate.engine.internal.Cascade;
|
||||
import org.hibernate.engine.internal.CascadePoint;
|
||||
import org.hibernate.engine.spi.CascadingAction;
|
||||
|
@ -27,6 +24,7 @@ import org.hibernate.engine.spi.SelfDirtinessTracker;
|
|||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.event.spi.EntityCopyObserver;
|
||||
import org.hibernate.event.spi.EntityCopyObserverFactory;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
import org.hibernate.event.spi.MergeEvent;
|
||||
import org.hibernate.event.spi.MergeEventListener;
|
||||
|
@ -48,8 +46,6 @@ import org.hibernate.type.TypeHelper;
|
|||
public class DefaultMergeEventListener extends AbstractSaveEventListener implements MergeEventListener {
|
||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( DefaultMergeEventListener.class );
|
||||
|
||||
private String entityCopyObserverStrategy;
|
||||
|
||||
@Override
|
||||
protected Map getMergeMap(Object anything) {
|
||||
return ( (MergeContext) anything ).invertMap();
|
||||
|
@ -77,23 +73,8 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme
|
|||
|
||||
private EntityCopyObserver createEntityCopyObserver(SessionFactoryImplementor sessionFactory) {
|
||||
final ServiceRegistry serviceRegistry = sessionFactory.getServiceRegistry();
|
||||
if ( entityCopyObserverStrategy == null ) {
|
||||
final ConfigurationService configurationService
|
||||
= serviceRegistry.getService( ConfigurationService.class );
|
||||
entityCopyObserverStrategy = configurationService.getSetting(
|
||||
AvailableSettings.MERGE_ENTITY_COPY_OBSERVER,
|
||||
new ConfigurationService.Converter<String>() {
|
||||
@Override
|
||||
public String convert(Object value) {
|
||||
return value.toString();
|
||||
}
|
||||
},
|
||||
EntityCopyNotAllowedObserver.SHORT_NAME
|
||||
);
|
||||
LOG.debugf( "EntityCopyObserver strategy: %s", entityCopyObserverStrategy );
|
||||
}
|
||||
final StrategySelector strategySelector = serviceRegistry.getService( StrategySelector.class );
|
||||
return strategySelector.resolveStrategy( EntityCopyObserver.class, entityCopyObserverStrategy );
|
||||
final EntityCopyObserverFactory configurationService = serviceRegistry.getService( EntityCopyObserverFactory.class );
|
||||
return configurationService.createEntityCopyObserver();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,6 +11,8 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.hibernate.event.spi.EntityCopyObserver;
|
||||
import org.hibernate.event.spi.EntityCopyObserverFactory;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
@ -24,9 +26,12 @@ import org.hibernate.pretty.MessageHelper;
|
|||
*
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class EntityCopyAllowedLoggedObserver extends EntityCopyAllowedObserver {
|
||||
public final class EntityCopyAllowedLoggedObserver implements EntityCopyObserver {
|
||||
|
||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( EntityCopyAllowedLoggedObserver.class );
|
||||
|
||||
public static final EntityCopyObserverFactory FACTORY_OF_SELF = () -> new EntityCopyAllowedLoggedObserver();
|
||||
|
||||
public static final String SHORT_NAME = "log";
|
||||
|
||||
// Tracks the number of entity copies per entity name.
|
||||
|
@ -39,13 +44,8 @@ public class EntityCopyAllowedLoggedObserver extends EntityCopyAllowedObserver {
|
|||
// key is the managed entity;
|
||||
// value is the set of representations being merged corresponding to the same managed result.
|
||||
|
||||
/**
|
||||
* Indicates if DEBUG logging is enabled.
|
||||
*
|
||||
* @return true, if DEBUG logging is enabled.
|
||||
*/
|
||||
public static boolean isDebugLoggingEnabled() {
|
||||
return LOG.isDebugEnabled();
|
||||
private EntityCopyAllowedLoggedObserver() {
|
||||
//Not to be constructed directly; use FACTORY_OF_SELF.
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.event.internal;
|
||||
|
||||
import org.hibernate.event.spi.EntityCopyObserver;
|
||||
import org.hibernate.event.spi.EntityCopyObserverFactory;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
|
||||
/**
|
||||
|
@ -15,9 +16,17 @@ import org.hibernate.event.spi.EventSource;
|
|||
*
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class EntityCopyAllowedObserver implements EntityCopyObserver {
|
||||
public final class EntityCopyAllowedObserver implements EntityCopyObserver {
|
||||
|
||||
public static final String SHORT_NAME = "allow";
|
||||
private static final EntityCopyObserver INSTANCE = new EntityCopyAllowedObserver();
|
||||
|
||||
//This implementation of EntityCopyObserver is stateless, so no need to create multiple copies:
|
||||
public static final EntityCopyObserverFactory FACTORY_OF_SELF = () -> INSTANCE;
|
||||
|
||||
private EntityCopyAllowedObserver() {
|
||||
//Not to be constructed; use INSTANCE.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void entityCopyDetected(
|
||||
|
@ -32,9 +41,9 @@ public class EntityCopyAllowedObserver implements EntityCopyObserver {
|
|||
// do nothing.
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void topLevelMergeComplete(EventSource session) {
|
||||
// do nothing.
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,15 +8,23 @@ package org.hibernate.event.internal;
|
|||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.event.spi.EntityCopyObserver;
|
||||
import org.hibernate.event.spi.EntityCopyObserverFactory;
|
||||
import org.hibernate.event.spi.EventSource;
|
||||
import org.hibernate.pretty.MessageHelper;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class EntityCopyNotAllowedObserver implements EntityCopyObserver {
|
||||
public final class EntityCopyNotAllowedObserver implements EntityCopyObserver {
|
||||
|
||||
public static final String SHORT_NAME = "disallow";
|
||||
private static final EntityCopyNotAllowedObserver INSTANCE = new EntityCopyNotAllowedObserver();
|
||||
//This implementation of EntityCopyObserver is stateless, so no need to create multiple copies:
|
||||
public static final EntityCopyObserverFactory FACTORY_OF_SELF = () -> INSTANCE;
|
||||
|
||||
private EntityCopyNotAllowedObserver() {
|
||||
//Not to be constructed; use INSTANCE.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void entityCopyDetected(
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* 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.event.internal;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.boot.registry.StandardServiceInitiator;
|
||||
import org.hibernate.boot.registry.selector.spi.StrategySelector;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.event.spi.EntityCopyObserver;
|
||||
import org.hibernate.event.spi.EntityCopyObserverFactory;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
|
||||
/**
|
||||
* Looks for the configuration property {@link AvailableSettings#MERGE_ENTITY_COPY_OBSERVER} and registers
|
||||
* the matching {@link EntityCopyObserverFactory} based on the configuration value.
|
||||
* <p>
|
||||
* For known implementations some optimisations are possible, such as reusing a singleton for the stateless
|
||||
* implementations. When a user plugs in a custom {@link EntityCopyObserver} we take a defensive approach.
|
||||
* </p>
|
||||
*/
|
||||
public class EntityCopyObserverFactoryInitiator implements StandardServiceInitiator<EntityCopyObserverFactory> {
|
||||
|
||||
public static final EntityCopyObserverFactoryInitiator INSTANCE = new EntityCopyObserverFactoryInitiator();
|
||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( EntityCopyObserverFactoryInitiator.class );
|
||||
|
||||
@Override
|
||||
public EntityCopyObserverFactory initiateService(final Map configurationValues, final ServiceRegistryImplementor registry) {
|
||||
final Object value = getConfigurationValue( configurationValues );
|
||||
if ( value.equals( EntityCopyNotAllowedObserver.SHORT_NAME ) || value.equals( EntityCopyNotAllowedObserver.class.getName() ) ) {
|
||||
LOG.debugf( "Configured EntityCopyObserver strategy: " + EntityCopyNotAllowedObserver.SHORT_NAME );
|
||||
return EntityCopyNotAllowedObserver.FACTORY_OF_SELF;
|
||||
}
|
||||
else if ( value.equals( EntityCopyAllowedObserver.SHORT_NAME ) || value.equals( EntityCopyAllowedObserver.class.getName() ) ) {
|
||||
LOG.debugf( "Configured EntityCopyObserver strategy: " + EntityCopyAllowedObserver.SHORT_NAME );
|
||||
return EntityCopyAllowedObserver.FACTORY_OF_SELF;
|
||||
}
|
||||
else if ( value.equals( EntityCopyAllowedLoggedObserver.SHORT_NAME ) || value.equals( EntityCopyAllowedLoggedObserver.class.getName() ) ) {
|
||||
LOG.debugf( "Configured EntityCopyObserver strategy: " + EntityCopyAllowedLoggedObserver.SHORT_NAME );
|
||||
return EntityCopyAllowedLoggedObserver.FACTORY_OF_SELF;
|
||||
}
|
||||
else {
|
||||
//We load an "example instance" just to get its Class;
|
||||
//this might look excessive, but it also happens to test eagerly (at boot) that we can actually construct these
|
||||
//and that they are indeed of the right type.
|
||||
EntityCopyObserver exampleInstance = registry.getService( StrategySelector.class ).resolveStrategy( EntityCopyObserver.class, value );
|
||||
Class observerType = exampleInstance.getClass();
|
||||
LOG.debugf( "Configured EntityCopyObserver is a custom implementation of type " + observerType.getName() );
|
||||
return new EntityObserversFactoryFromClass( observerType );
|
||||
}
|
||||
}
|
||||
|
||||
private Object getConfigurationValue(final Map configurationValues) {
|
||||
final Object o = configurationValues.get( AvailableSettings.MERGE_ENTITY_COPY_OBSERVER );
|
||||
if ( o == null ) {
|
||||
return EntityCopyNotAllowedObserver.SHORT_NAME; //default
|
||||
}
|
||||
else if ( o instanceof String ) {
|
||||
return o.toString().trim();
|
||||
}
|
||||
else {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<EntityCopyObserverFactory> getServiceInitiated() {
|
||||
return EntityCopyObserverFactory.class;
|
||||
}
|
||||
|
||||
private static class EntityObserversFactoryFromClass implements EntityCopyObserverFactory {
|
||||
|
||||
private final Class value;
|
||||
|
||||
public EntityObserversFactoryFromClass(Class value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityCopyObserver createEntityCopyObserver() {
|
||||
try {
|
||||
return (EntityCopyObserver) value.newInstance();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException( "Could not instantiate class of type " + value.getName() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* 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.event.spi;
|
||||
|
||||
import org.hibernate.service.Service;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface EntityCopyObserverFactory extends Service {
|
||||
EntityCopyObserver createEntityCopyObserver();
|
||||
}
|
|
@ -25,6 +25,7 @@ import org.hibernate.engine.jdbc.internal.JdbcServicesInitiator;
|
|||
import org.hibernate.engine.jndi.internal.JndiServiceInitiator;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformResolverInitiator;
|
||||
import org.hibernate.event.internal.EntityCopyObserverFactoryInitiator;
|
||||
import org.hibernate.hql.internal.QueryTranslatorFactoryInitiator;
|
||||
import org.hibernate.id.factory.internal.MutableIdentifierGeneratorFactoryInitiator;
|
||||
import org.hibernate.jmx.internal.JmxServiceInitiator;
|
||||
|
@ -86,6 +87,7 @@ public final class StandardServiceInitiators {
|
|||
serviceInitiators.add( TransactionCoordinatorBuilderInitiator.INSTANCE );
|
||||
|
||||
serviceInitiators.add( ManagedBeanRegistryInitiator.INSTANCE );
|
||||
serviceInitiators.add( EntityCopyObserverFactoryInitiator.INSTANCE );
|
||||
|
||||
serviceInitiators.trimToSize();
|
||||
|
||||
|
|
Loading…
Reference in New Issue