-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
HHH-15422 Pick up CurrentTenantIdentifierResolver and MultiTenantConnectionProvider from BeanContainer if not explicit set
#8697
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -63,6 +63,10 @@ | |
| import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy; | ||
| import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; | ||
| import org.hibernate.query.sqm.sql.SqmTranslatorFactory; | ||
| import org.hibernate.resource.beans.container.spi.BeanContainer; | ||
| import org.hibernate.resource.beans.internal.Helper; | ||
| import org.hibernate.resource.beans.spi.BeanInstanceProducer; | ||
| import org.hibernate.resource.beans.spi.ManagedBeanRegistry; | ||
| import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode; | ||
| import org.hibernate.resource.jdbc.spi.StatementInspector; | ||
| import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder; | ||
|
|
@@ -283,6 +287,7 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions { | |
| private final int queryStatisticsMaxSize; | ||
|
|
||
|
|
||
| @SuppressWarnings( "unchecked" ) | ||
| public SessionFactoryOptionsBuilder(StandardServiceRegistry serviceRegistry, BootstrapContext context) { | ||
| this.serviceRegistry = serviceRegistry; | ||
| this.jpaBootstrap = context.isJpaBootstrap(); | ||
|
|
@@ -372,6 +377,38 @@ public SessionFactoryOptionsBuilder(StandardServiceRegistry serviceRegistry, Boo | |
| CurrentTenantIdentifierResolver.class, | ||
| configurationSettings.get( MULTI_TENANT_IDENTIFIER_RESOLVER ) | ||
| ); | ||
| if ( this.currentTenantIdentifierResolver == null ) { | ||
| final BeanContainer beanContainer = Helper.allowExtensionsInCdi( serviceRegistry ) ? serviceRegistry.requireService( ManagedBeanRegistry.class ).getBeanContainer() : null; | ||
| if (beanContainer != null) { | ||
| this.currentTenantIdentifierResolver = beanContainer.getBean( | ||
| CurrentTenantIdentifierResolver.class, | ||
| new BeanContainer.LifecycleOptions() { | ||
| @Override | ||
| public boolean canUseCachedReferences() { | ||
| return true; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean useJpaCompliantCreation() { | ||
| return false; | ||
| } | ||
| }, | ||
| new BeanInstanceProducer() { | ||
|
|
||
| @Override | ||
| public <B> B produceBeanInstance(Class<B> beanType) { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public <B> B produceBeanInstance(String name, Class<B> beanType) { | ||
| return null; | ||
| } | ||
|
|
||
| } | ||
| ).getBeanInstance(); | ||
| } | ||
|
Comment on lines
+381
to
+410
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please extract out a function for this, the constructor is already waaaaaay too long.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gavinking I suggest to introduce new util methods for @SuppressWarnings( "unchecked" )
public static <T> T getBean(ServiceRegistry serviceRegistry, Class<?> beanType, boolean canUseCachedReferences, boolean useJpaCompliantCreation, T fallback) {
final BeanContainer beanContainer = allowExtensionsInCdi( serviceRegistry ) ? serviceRegistry.requireService( ManagedBeanRegistry.class ).getBeanContainer() : null;
if ( beanContainer == null ) {
return null;
}
return (T) beanContainer.getBean(
beanType,
new BeanContainer.LifecycleOptions() {
@Override
public boolean canUseCachedReferences() {
return canUseCachedReferences;
}
@Override
public boolean useJpaCompliantCreation() {
return useJpaCompliantCreation;
}
},
new BeanInstanceProducer() {
@Override
public <B> B produceBeanInstance(Class<B> beanType) {
return (B) fallback;
}
@Override
public <B> B produceBeanInstance(String name, Class<B> beanType) {
throw new UnsupportedOperationException("The method shouldn't be called");
}
}
).getBeanInstance();
}
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That sounds fine to me, but please do it now, so that it doesn't get forgotten. Thanks.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I created https://hibernate.atlassian.net/browse/HHH-18737 just now.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, great, thanks 🙏 |
||
| } | ||
|
|
||
| this.delayBatchFetchLoaderCreations = configurationService.getSetting( DELAY_ENTITY_LOADER_CREATIONS, BOOLEAN, true ); | ||
| this.defaultBatchFetchSize = getInt( DEFAULT_BATCH_FETCH_SIZE, configurationSettings, -1 ); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |
| */ | ||
| package org.hibernate.engine.jdbc.connections.internal; | ||
|
|
||
| import java.lang.reflect.InvocationTargetException; | ||
| import java.sql.Connection; | ||
| import java.util.Collection; | ||
| import java.util.HashSet; | ||
|
|
@@ -19,6 +20,11 @@ | |
| import org.hibernate.internal.CoreLogging; | ||
| import org.hibernate.internal.CoreMessageLogger; | ||
| import org.hibernate.internal.util.StringHelper; | ||
| import org.hibernate.resource.beans.container.spi.BeanContainer; | ||
| import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer; | ||
| import org.hibernate.resource.beans.internal.Helper; | ||
| import org.hibernate.resource.beans.spi.BeanInstanceProducer; | ||
| import org.hibernate.resource.beans.spi.ManagedBeanRegistry; | ||
| import org.hibernate.service.spi.ServiceRegistryImplementor; | ||
|
|
||
| import static java.sql.Connection.TRANSACTION_NONE; | ||
|
|
@@ -102,6 +108,7 @@ public ConnectionProvider initiateService( | |
| return null; | ||
| } | ||
|
|
||
| final BeanContainer beanContainer = Helper.allowExtensionsInCdi( registry ) ? registry.requireService( ManagedBeanRegistry.class ).getBeanContainer() : null; | ||
| final StrategySelector strategySelector = registry.requireService( StrategySelector.class ); | ||
| final Object explicitSetting = configurationValues.get( CONNECTION_PROVIDER ); | ||
| if ( explicitSetting != null ) { | ||
|
|
@@ -111,25 +118,25 @@ public ConnectionProvider initiateService( | |
| } | ||
| else if ( explicitSetting instanceof Class<?> providerClass ) { | ||
| LOG.instantiatingExplicitConnectionProvider( providerClass.getName() ); | ||
| return instantiateExplicitConnectionProvider( providerClass ); | ||
| return instantiateExplicitConnectionProvider( providerClass, beanContainer ); | ||
| } | ||
| else { | ||
| final String providerName = nullIfEmpty( explicitSetting.toString() ); | ||
| if ( providerName != null ) { | ||
| return instantiateNamedConnectionProvider(providerName, strategySelector); | ||
| return instantiateNamedConnectionProvider(providerName, strategySelector, beanContainer); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return instantiateConnectionProvider( configurationValues, strategySelector ); | ||
| return instantiateConnectionProvider( configurationValues, strategySelector, beanContainer ); | ||
| } | ||
|
|
||
| private ConnectionProvider instantiateNamedConnectionProvider(String providerName, StrategySelector strategySelector) { | ||
| private ConnectionProvider instantiateNamedConnectionProvider(String providerName, StrategySelector strategySelector, BeanContainer beanContainer) { | ||
| LOG.instantiatingExplicitConnectionProvider( providerName ); | ||
| final Class<?> providerClass = | ||
| strategySelector.selectStrategyImplementor( ConnectionProvider.class, providerName ); | ||
| try { | ||
| return instantiateExplicitConnectionProvider( providerClass ); | ||
| return instantiateExplicitConnectionProvider( providerClass, beanContainer ); | ||
| } | ||
| catch (Exception e) { | ||
| throw new HibernateException( | ||
|
|
@@ -140,7 +147,7 @@ private ConnectionProvider instantiateNamedConnectionProvider(String providerNam | |
| } | ||
|
|
||
| private ConnectionProvider instantiateConnectionProvider( | ||
| Map<String, Object> configurationValues, StrategySelector strategySelector) { | ||
| Map<String, Object> configurationValues, StrategySelector strategySelector, BeanContainer beanContainer) { | ||
| if ( configurationValues.containsKey( DATASOURCE ) ) { | ||
| return new DatasourceConnectionProviderImpl(); | ||
| } | ||
|
|
@@ -149,9 +156,9 @@ private ConnectionProvider instantiateConnectionProvider( | |
| getSingleRegisteredProvider( strategySelector ); | ||
| if ( singleRegisteredProvider != null ) { | ||
| try { | ||
| return singleRegisteredProvider.newInstance(); | ||
| return singleRegisteredProvider.getConstructor().newInstance(); | ||
| } | ||
| catch (IllegalAccessException | InstantiationException e) { | ||
| catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException | InstantiationException e) { | ||
| throw new HibernateException( "Could not instantiate singular-registered ConnectionProvider", e ); | ||
| } | ||
| } | ||
|
|
@@ -177,11 +184,47 @@ else if ( configurationValues.containsKey( URL ) ) { | |
| return new DriverManagerConnectionProviderImpl(); | ||
| } | ||
| else { | ||
| LOG.noAppropriateConnectionProvider(); | ||
| return new UserSuppliedConnectionProviderImpl(); | ||
| if (beanContainer != null) { | ||
| return beanContainer.getBean( | ||
| ConnectionProvider.class, | ||
| new BeanContainer.LifecycleOptions() { | ||
| @Override | ||
| public boolean canUseCachedReferences() { | ||
| return true; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean useJpaCompliantCreation() { | ||
| return true; | ||
| } | ||
| }, | ||
| new BeanInstanceProducer() { | ||
|
|
||
| @Override | ||
| public <B> B produceBeanInstance(Class<B> beanType) { | ||
| return (B) noAppropriateConnectionProvider(); | ||
| } | ||
|
|
||
| @Override | ||
| public <B> B produceBeanInstance(String name, Class<B> beanType) { | ||
| return (B) noAppropriateConnectionProvider(); | ||
| } | ||
|
|
||
| } | ||
| ).getBeanInstance(); | ||
| } | ||
| else { | ||
| return noAppropriateConnectionProvider(); | ||
| } | ||
|
|
||
| } | ||
|
Comment on lines
+188
to
220
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similarly, please extract a function. |
||
| } | ||
|
|
||
| private ConnectionProvider noAppropriateConnectionProvider() { | ||
| LOG.noAppropriateConnectionProvider(); | ||
| return new UserSuppliedConnectionProviderImpl(); | ||
| } | ||
|
|
||
| private Class<? extends ConnectionProvider> getSingleRegisteredProvider(StrategySelector strategySelector) { | ||
| final Collection<Class<? extends ConnectionProvider>> implementors = | ||
| strategySelector.getRegisteredStrategyImplementors( ConnectionProvider.class ); | ||
|
|
@@ -190,9 +233,28 @@ private Class<? extends ConnectionProvider> getSingleRegisteredProvider(Strategy | |
| : null; | ||
| } | ||
|
|
||
| private ConnectionProvider instantiateExplicitConnectionProvider(Class<?> providerClass) { | ||
| private ConnectionProvider instantiateExplicitConnectionProvider(Class<?> providerClass, BeanContainer beanContainer) { | ||
| try { | ||
| return (ConnectionProvider) providerClass.newInstance(); | ||
| if ( beanContainer != null ) { | ||
| return (ConnectionProvider) beanContainer.getBean( | ||
| providerClass, | ||
| new BeanContainer.LifecycleOptions() { | ||
| @Override | ||
| public boolean canUseCachedReferences() { | ||
| return true; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean useJpaCompliantCreation() { | ||
| return true; | ||
| } | ||
| }, | ||
| FallbackBeanInstanceProducer.INSTANCE | ||
| ).getBeanInstance(); | ||
| } | ||
| else { | ||
| return (ConnectionProvider) providerClass.getConstructor().newInstance(); | ||
| } | ||
| } | ||
| catch (Exception e) { | ||
| throw new HibernateException( "Could not instantiate connection provider [" + providerClass.getName() + "]", e ); | ||
|
|
@@ -201,7 +263,7 @@ private ConnectionProvider instantiateExplicitConnectionProvider(Class<?> provid | |
|
|
||
| private static ConnectionProvider instantiateProvider(StrategySelector selector, String strategy) { | ||
| try { | ||
| return selector.selectStrategyImplementor( ConnectionProvider.class, strategy ).newInstance(); | ||
| return selector.selectStrategyImplementor( ConnectionProvider.class, strategy ).getConstructor().newInstance(); | ||
| } | ||
| catch ( Exception e ) { | ||
| LOG.providerClassNotFound(strategy); | ||
|
|
||
beikov marked this conversation as resolved.
Show resolved
Hide resolved
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,6 +12,10 @@ | |
| import org.hibernate.cfg.AvailableSettings; | ||
| import org.hibernate.engine.jdbc.connections.spi.DataSourceBasedMultiTenantConnectionProviderImpl; | ||
| import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider; | ||
| import org.hibernate.resource.beans.container.spi.BeanContainer; | ||
| import org.hibernate.resource.beans.internal.Helper; | ||
| import org.hibernate.resource.beans.spi.BeanInstanceProducer; | ||
| import org.hibernate.resource.beans.spi.ManagedBeanRegistry; | ||
| import org.hibernate.service.spi.ServiceException; | ||
| import org.hibernate.service.spi.ServiceRegistryImplementor; | ||
|
|
||
|
|
@@ -39,7 +43,36 @@ public Class<MultiTenantConnectionProvider<?>> getServiceInitiated() { | |
| @Override | ||
| public MultiTenantConnectionProvider<?> initiateService(Map<String, Object> configurationValues, ServiceRegistryImplementor registry) { | ||
| if ( !configurationValues.containsKey( AvailableSettings.MULTI_TENANT_CONNECTION_PROVIDER ) ) { | ||
| // nothing to do, but given the separate hierarchies have to handle this here. | ||
| final BeanContainer beanContainer = Helper.allowExtensionsInCdi( registry ) ? registry.requireService( ManagedBeanRegistry.class ).getBeanContainer() : null; | ||
beikov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if (beanContainer != null) { | ||
| return beanContainer.getBean( | ||
| MultiTenantConnectionProvider.class, | ||
| new BeanContainer.LifecycleOptions() { | ||
| @Override | ||
| public boolean canUseCachedReferences() { | ||
| return true; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean useJpaCompliantCreation() { | ||
| return true; | ||
| } | ||
| }, | ||
| new BeanInstanceProducer() { | ||
|
|
||
| @Override | ||
| public <B> B produceBeanInstance(Class<B> beanType) { | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public <B> B produceBeanInstance(String name, Class<B> beanType) { | ||
| return null; | ||
| } | ||
|
|
||
| } | ||
| ).getBeanInstance(); | ||
| } | ||
|
Comment on lines
+46
to
+75
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similarly, extract a function here, please. |
||
| return null; | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.