下面列出了怎么用org.hibernate.MultiTenancyStrategy的API类实例代码及写法,或者点击链接到github查看源代码。
@BuildStep
@Record(STATIC_INIT)
public void build(HibernateOrmRecorder recorder,
Capabilities capabilities, BuildProducer<BeanContainerListenerBuildItem> buildProducer,
List<PersistenceUnitDescriptorBuildItem> descriptors,
JpaEntitiesBuildItem jpaEntities, List<NonJpaModelBuildItem> nonJpaModels) throws Exception {
if (!hasEntities(jpaEntities, nonJpaModels)) {
return;
}
MultiTenancyStrategy strategy = MultiTenancyStrategy
.valueOf(hibernateConfig.multitenant.orElse(MultiTenancyStrategy.NONE.name()));
buildProducer.produce(new BeanContainerListenerBuildItem(
recorder.initializeJpa(capabilities.isPresent(Capability.TRANSACTIONS), strategy,
hibernateConfig.multitenantSchemaDatasource.orElse(null))));
// Bootstrap all persistence units
for (PersistenceUnitDescriptorBuildItem persistenceUnitDescriptor : descriptors) {
buildProducer.produce(new BeanContainerListenerBuildItem(
recorder.registerPersistenceUnit(persistenceUnitDescriptor.getDescriptor().getName())));
}
buildProducer.produce(new BeanContainerListenerBuildItem(recorder.initDefaultPersistenceUnit()));
}
@Override
public ConnectionProvider resolve(String tenantId) {
LOG.debugv("resolve({0})", tenantId);
final MultiTenancyStrategy strategy = jpaConfig.getMultiTenancyStrategy();
LOG.debugv("multitenancy strategy: {0}", strategy);
AgroalDataSource dataSource = tenantDataSource(jpaConfig, tenantId, strategy);
if (dataSource == null) {
throw new IllegalStateException("No instance of datasource found for tenant: " + tenantId);
}
if (strategy == MultiTenancyStrategy.SCHEMA) {
return new TenantConnectionProvider(tenantId, dataSource);
}
return new QuarkusConnectionProvider(dataSource);
}
private static Map<String, RecordedState> constructMetadataAdvance(
final List<PersistenceUnitDescriptor> parsedPersistenceXmlDescriptors, Scanner scanner,
Collection<Class<? extends Integrator>> additionalIntegrators,
PreGeneratedProxies proxyClassDefinitions,
MultiTenancyStrategy strategy) {
Map<String, RecordedState> recordedStates = new HashMap<>();
for (PersistenceUnitDescriptor unit : parsedPersistenceXmlDescriptors) {
RecordedState m = createMetadata(unit, scanner, additionalIntegrators, proxyClassDefinitions, strategy);
Object previous = recordedStates.put(unitName(unit), m);
if (previous != null) {
throw new IllegalStateException("Duplicate persistence unit name: " + unit.getName());
}
}
return recordedStates;
}
/**
* org.springframework.beans.factory.FactoryBean that creates a JPA
* {@link javax.persistence.EntityManagerFactory} according to JPA's standard
* container bootstrap contract. This is the most powerful way to set up a
* shared JPA EntityManagerFactory in a Spring application context; the
* EntityManagerFactory can then be passed to JPA-based DAOs via dependency
* injection. Note that switching to a JNDI lookup or to a
* {@link org.springframework.orm.jpa.LocalEntityManagerFactoryBean} definition
* is just a matter of configuration!
*
* @param multiTenantConnectionProvider
* @param currentTenantIdentifierResolver
* @return
*/
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(
MultiTenantConnectionProvider multiTenantConnectionProvider,
CurrentTenantIdentifierResolver currentTenantIdentifierResolver) {
Map<String, Object> hibernateProps = new LinkedHashMap<>();
hibernateProps.putAll(this.jpaProperties.getProperties());
hibernateProps.put(Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE);
hibernateProps.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER, multiTenantConnectionProvider);
hibernateProps.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, currentTenantIdentifierResolver);
// No dataSource is set to resulting entityManagerFactoryBean
LocalContainerEntityManagerFactoryBean result = new LocalContainerEntityManagerFactoryBean();
result.setPackagesToScan(new String[] { Employee.class.getPackage().getName() });
result.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
result.setJpaPropertyMap(hibernateProps);
return result;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, MultiTenantConnectionProvider multiTenantConnectionProvider,
CurrentTenantIdentifierResolver tenantIdentifierResolver) {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("com.mycompany.models");
em.setJpaVendorAdapter(this.jpaVendorAdapter());
final Map<String, Object> jpaProperties = new HashMap<>();
jpaProperties.put(Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA);
jpaProperties.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER, multiTenantConnectionProvider);
jpaProperties.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantIdentifierResolver);
jpaProperties.put(Environment.FORMAT_SQL, true);
em.setJpaPropertyMap(jpaProperties);
return em;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
MultiTenantConnectionProvider multiTenantConnectionProviderImpl,
CurrentTenantIdentifierResolver currentTenantIdentifierResolverImpl) {
Map<String, Object> properties = new HashMap<>();
properties.putAll(jpaProperties.getHibernateProperties(dataSource));
properties.put(Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA);
properties.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER, multiTenantConnectionProviderImpl);
properties.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, currentTenantIdentifierResolverImpl);
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("com.srai");
em.setJpaVendorAdapter(jpaVendorAdapter());
em.setJpaPropertyMap(properties);
return em;
}
private MultiTenancyStrategy getMultiTenancyStrategy() {
final MultiTenancyStrategy multiTenancyStrategy = MultiTenancyStrategy
.valueOf(hibernateConfig.multitenant.orElse(MultiTenancyStrategy.NONE.name()));
if (multiTenancyStrategy == MultiTenancyStrategy.DISCRIMINATOR) {
// See https://hibernate.atlassian.net/browse/HHH-6054
throw new ConfigurationError("The Hibernate ORM multi tenancy strategy "
+ MultiTenancyStrategy.DISCRIMINATOR + " is currently not supported");
}
return multiTenancyStrategy;
}
@BuildStep
void registerBeans(BuildProducer<AdditionalBeanBuildItem> additionalBeans, Capabilities capabilities,
CombinedIndexBuildItem combinedIndex,
List<PersistenceUnitDescriptorBuildItem> descriptors,
JpaEntitiesBuildItem jpaEntities, List<NonJpaModelBuildItem> nonJpaModels) {
if (!hasEntities(jpaEntities, nonJpaModels)) {
return;
}
List<Class<?>> unremovableClasses = new ArrayList<>();
unremovableClasses.add(JPAConfig.class);
if (capabilities.isPresent(Capability.TRANSACTIONS)) {
unremovableClasses.add(TransactionManager.class);
unremovableClasses.add(TransactionEntityManagers.class);
}
unremovableClasses.add(RequestScopedEntityManagerHolder.class);
if (getMultiTenancyStrategy() != MultiTenancyStrategy.NONE) {
unremovableClasses.add(DataSourceTenantConnectionResolver.class);
}
additionalBeans.produce(AdditionalBeanBuildItem.builder().setUnremovable()
.addBeanClasses(unremovableClasses.toArray(new Class<?>[unremovableClasses.size()]))
.build());
if (descriptors.size() == 1) {
// There is only one persistence unit - register CDI beans for EM and EMF if no
// producers are defined
if (isUserDefinedProducerMissing(combinedIndex.getIndex(), PERSISTENCE_UNIT)) {
additionalBeans.produce(new AdditionalBeanBuildItem(DefaultEntityManagerFactoryProducer.class));
}
if (isUserDefinedProducerMissing(combinedIndex.getIndex(), PERSISTENCE_CONTEXT)) {
additionalBeans.produce(new AdditionalBeanBuildItem(DefaultEntityManagerProducer.class));
}
}
}
public RecordedState(Dialect dialect, PrevalidatedQuarkusMetadata metadata,
BuildTimeSettings settings, Collection<Integrator> integrators,
Collection<ProvidedService> providedServices, IntegrationSettings integrationSettings,
ProxyDefinitions classDefinitions, MultiTenancyStrategy strategy) {
this.dialect = dialect;
this.metadata = metadata;
this.settings = settings;
this.integrators = integrators;
this.providedServices = providedServices;
this.integrationSettings = integrationSettings;
this.proxyClassDefinitions = classDefinitions;
this.multiTenancyStrategy = strategy;
}
/**
* Initializes the JPA configuration to be used at runtime.
*
* @param jtaEnabled Should JTA be enabled?
* @param strategy Multitenancy strategy to use.
* @param multiTenancySchemaDataSource Data source to use in case of {@link MultiTenancyStrategy#SCHEMA} approach or
* {@link null} in case the default data source.
*
* @return
*/
public BeanContainerListener initializeJpa(boolean jtaEnabled, MultiTenancyStrategy strategy,
String multiTenancySchemaDataSource) {
return new BeanContainerListener() {
@Override
public void created(BeanContainer beanContainer) {
JPAConfig instance = beanContainer.instance(JPAConfig.class);
instance.setJtaEnabled(jtaEnabled);
instance.setMultiTenancyStrategy(strategy);
instance.setMultiTenancySchemaDataSource(multiTenancySchemaDataSource);
}
};
}
public BeanContainerListener initMetadata(List<ParsedPersistenceXmlDescriptor> parsedPersistenceXmlDescriptors,
Scanner scanner, Collection<Class<? extends Integrator>> additionalIntegrators,
PreGeneratedProxies proxyDefinitions, MultiTenancyStrategy strategy) {
return new BeanContainerListener() {
@Override
public void created(BeanContainer beanContainer) {
PersistenceUnitsHolder.initializeJpa(parsedPersistenceXmlDescriptors, scanner, additionalIntegrators,
proxyDefinitions, strategy);
}
};
}
/**
* Returns either the default data source or the tenant specific one.
*
* @param tenantId Tenant identifier. The value is required (non-{@literal null}) in case of
* {@link MultiTenancyStrategy#DATABASE}.
* @param strategy Current multitenancy strategy Required value that cannot be {@literal null}.
*
* @return Data source.
*/
private static AgroalDataSource tenantDataSource(JPAConfig jpaConfig, String tenantId, MultiTenancyStrategy strategy) {
if (strategy != MultiTenancyStrategy.SCHEMA) {
return Arc.container().instance(AgroalDataSource.class, new DataSource.DataSourceLiteral(tenantId)).get();
}
String dataSourceName = jpaConfig.getMultiTenancySchemaDataSource();
if (dataSourceName == null) {
AgroalDataSource dataSource = Arc.container().instance(AgroalDataSource.class).get();
return createFrom(dataSource.getConfiguration());
}
return Arc.container().instance(AgroalDataSource.class, new DataSource.DataSourceLiteral(dataSourceName)).get();
}
public static RecordedState createMetadata(PersistenceUnitDescriptor unit, Scanner scanner,
Collection<Class<? extends Integrator>> additionalIntegrators, PreGeneratedProxies proxyDefinitions,
MultiTenancyStrategy strategy) {
FastBootMetadataBuilder fastBootMetadataBuilder = new FastBootMetadataBuilder(unit, scanner, additionalIntegrators,
proxyDefinitions, strategy);
return fastBootMetadataBuilder.build();
}
public JPAConfig() {
this.jtaEnabled = new AtomicBoolean();
this.multiTenancyStrategy = new AtomicReference<MultiTenancyStrategy>();
this.multiTenancySchemaDataSource = new AtomicReference<String>();
this.persistenceUnits = new ConcurrentHashMap<>();
this.defaultPersistenceUnitName = new AtomicReference<String>();
}
public FastBootEntityManagerFactoryBuilder(
PrevalidatedQuarkusMetadata metadata, String persistenceUnitName,
StandardServiceRegistry standardServiceRegistry, RuntimeSettings runtimeSettings, Object validatorFactory,
Object cdiBeanManager, MultiTenancyStrategy strategy) {
this.metadata = metadata;
this.persistenceUnitName = persistenceUnitName;
this.standardServiceRegistry = standardServiceRegistry;
this.runtimeSettings = runtimeSettings;
this.validatorFactory = validatorFactory;
this.cdiBeanManager = cdiBeanManager;
this.multiTenancyStrategy = strategy;
}
@Override
public ReactiveConnectionPool initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
//First, check that this setup won't need to deal with multi-tenancy at the connection pool level:
final MultiTenancyStrategy strategy = MultiTenancyStrategy.determineMultiTenancyStrategy(configurationValues);
if (strategy == MultiTenancyStrategy.DATABASE || strategy == MultiTenancyStrategy.SCHEMA) {
// nothing to do, but given the separate hierarchies have to handle this here.
return null;
}
return new QuarkusReactiveConnectionPool(pool);
}
private JdbcConnectionAccess buildJdbcConnectionAccess(Map configValues, ServiceRegistryImplementor registry) {
final MultiTenancyStrategy multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy(
configValues
);
if ( !multiTenancyStrategy.requiresMultiTenantConnectionProvider() ) {
ConnectionProvider connectionProvider = registry.getService( ConnectionProvider.class );
return new ConnectionProviderJdbcConnectionAccess( connectionProvider );
}
else {
final MultiTenantConnectionProvider multiTenantConnectionProvider = registry.getService( MultiTenantConnectionProvider.class );
return new MultiTenantConnectionProviderJdbcConnectionAccess( multiTenantConnectionProvider );
}
}
public static JdbcConnectionAccess buildBootstrapJdbcConnectionAccess(
MultiTenancyStrategy multiTenancyStrategy,
ServiceRegistryImplementor registry) {
if ( !multiTenancyStrategy.requiresMultiTenantConnectionProvider() ) {
ConnectionProvider connectionProvider = registry.getService( ConnectionProvider.class );
return new ConnectionProviderJdbcConnectionAccess( connectionProvider );
}
else {
final MultiTenantConnectionProvider multiTenantConnectionProvider = registry.getService( MultiTenantConnectionProvider.class );
return new MultiTenantConnectionProviderJdbcConnectionAccess( multiTenantConnectionProvider );
}
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder) {
Map<String, Object> hibernateProps = new LinkedHashMap<>();
hibernateProps.putAll(jpaProperties.getHibernateProperties(dataSource));
hibernateProps.put(Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE);
hibernateProps.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER, multiTenantConnectionProvider);
hibernateProps.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, currentTenantIdentifierResolver);
hibernateProps.put(Environment.DIALECT, "org.hibernate.dialect.MySQLDialect");
return builder.dataSource(dataSource).packages(Employee.class.getPackage().getName()).properties(hibernateProps).jta(false).build();
}
@Override
protected void additionalProperties(Properties properties) {
properties.setProperty(AvailableSettings.HBM2DDL_AUTO, "none");
properties.setProperty(AvailableSettings.MULTI_TENANT, MultiTenancyStrategy.SCHEMA.name());
properties.setProperty(AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER, TenantContext.TenantIdentifierResolver.class.getName());
properties.put(AvailableSettings.MULTI_TENANT_CONNECTION_PROVIDER, MultiTenantConnectionProvider.INSTANCE);
}
@Override
protected void additionalProperties(Properties properties) {
properties.setProperty(AvailableSettings.HBM2DDL_AUTO, "none");
properties.setProperty(AvailableSettings.SHOW_SQL, "true");
properties.setProperty(AvailableSettings.MULTI_TENANT, MultiTenancyStrategy.DATABASE.name());
properties.put(AvailableSettings.MULTI_TENANT_CONNECTION_PROVIDER, MultiTenantConnectionProvider.INSTANCE);
properties.setProperty(AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER, TenantContext.TenantIdentifierResolver.class.getName());
}
public
@Bean
EntityManagerFactory customEntityManagerFactory(DataSource dataSource) {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(false); // turn off with Discriminator strategy so far!
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan(TenancySampleApplication.class.getPackage().getName());
factory.setDataSource(dataSource);
factory.getJpaPropertyMap().put(Environment.DIALECT, PostgreSQL9Dialect.class.getName());
factory.getJpaPropertyMap().put(Environment.MULTI_TENANT, MultiTenancyStrategy.DISCRIMINATOR);
factory.getJpaPropertyMap().put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, new TenantHolder());
factory.afterPropertiesSet();
return factory.getObject();
}
public MultiTenancyStrategy getMultiTenancyStrategy() {
return multiTenancyStrategy;
}
protected void populate(SessionFactoryOptionsBuilder options, StandardServiceRegistry ssr, MultiTenancyStrategy strategy) {
// 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) {
options.disableJtaTransactionAccess();
}
final boolean allowRefreshDetachedEntity = runtimeSettings.getBoolean(
org.hibernate.cfg.AvailableSettings.ALLOW_REFRESH_DETACHED_ENTITY);
if (!allowRefreshDetachedEntity) {
options.disableRefreshDetachedEntity();
}
// Locate and apply any requested SessionFactoryObserver
final Object sessionFactoryObserverSetting = runtimeSettings.get(AvailableSettings.SESSION_FACTORY_OBSERVER);
if (sessionFactoryObserverSetting != null) {
final StrategySelector strategySelector = ssr.getService(StrategySelector.class);
final SessionFactoryObserver suppliedSessionFactoryObserver = strategySelector
.resolveStrategy(SessionFactoryObserver.class, sessionFactoryObserverSetting);
options.addSessionFactoryObservers(suppliedSessionFactoryObserver);
}
options.addSessionFactoryObservers(new ServiceRegistryCloser());
options.applyEntityNotFoundDelegate(new JpaEntityNotFoundDelegate());
if (this.validatorFactory != null) {
options.applyValidatorFactory(validatorFactory);
}
if (this.cdiBeanManager != null) {
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));
if (strategy != null && strategy != MultiTenancyStrategy.NONE) {
options.applyMultiTenancyStrategy(strategy);
options.applyCurrentTenantIdentifierResolver(new HibernateCurrentTenantIdentifierResolver());
}
}
@SuppressWarnings("unchecked")
public FastBootMetadataBuilder(final PersistenceUnitDescriptor persistenceUnit, Scanner scanner,
Collection<Class<? extends Integrator>> additionalIntegrators, PreGeneratedProxies preGeneratedProxies,
MultiTenancyStrategy strategy) {
this.persistenceUnit = persistenceUnit;
this.additionalIntegrators = additionalIntegrators;
this.preGeneratedProxies = preGeneratedProxies;
final ClassLoaderService providedClassLoaderService = FlatClassLoaderService.INSTANCE;
// Copying semantics from: new EntityManagerFactoryBuilderImpl( unit,
// integration, instance );
// Except we remove support for several legacy features and XML binding
final ClassLoader providedClassLoader = null;
LogHelper.logPersistenceUnitInformation(persistenceUnit);
// Build the boot-strap service registry, which mainly handles class loader
// interactions
final BootstrapServiceRegistry bsr = buildBootstrapServiceRegistry(providedClassLoaderService);
// merge configuration sources and build the "standard" service registry
final RecordableBootstrap ssrBuilder = new RecordableBootstrap(bsr);
final MergedSettings mergedSettings = mergeSettings(persistenceUnit);
this.buildTimeSettings = new BuildTimeSettings(mergedSettings.getConfigurationValues());
// Build the "standard" service registry
ssrBuilder.applySettings(buildTimeSettings.getSettings());
this.standardServiceRegistry = ssrBuilder.build();
registerIdentifierGenerators(standardServiceRegistry);
this.providedServices = ssrBuilder.getProvidedServices();
/**
* This is required to properly integrate Hibernate Envers.
*
* The EnversService requires multiple steps to be properly built, the most important ones are:
*
* 1. The EnversServiceContributor contributes the EnversServiceInitiator to the RecordableBootstrap.
* 2. After RecordableBootstrap builds a StandardServiceRegistry, the first time the EnversService is
* requested, it is created by the initiator and configured by the registry.
* 3. The MetadataBuildingProcess completes by calling the AdditionalJaxbMappingProducer which
* initializes the EnversService and produces some additional mapping documents.
* 4. After that point the EnversService appears to be fully functional.
*
* The following trick uses the aforementioned steps to setup the EnversService and then turns it into
* a ProvidedService so that it is not necessary to repeat all these complex steps during the reactivation
* of the destroyed service registry in PreconfiguredServiceRegistryBuilder.
*
*/
for (Class<? extends Service> postBuildProvidedService : ssrBuilder.getPostBuildProvidedServices()) {
providedServices.add(new ProvidedService(postBuildProvidedService,
standardServiceRegistry.getService(postBuildProvidedService)));
}
final MetadataSources metadataSources = new MetadataSources(bsr);
addPUManagedClassNamesToMetadataSources(persistenceUnit, metadataSources);
this.metamodelBuilder = (MetadataBuilderImplementor) metadataSources
.getMetadataBuilder(standardServiceRegistry);
if (scanner != null) {
this.metamodelBuilder.applyScanner(scanner);
}
populate(metamodelBuilder, mergedSettings.cacheRegionDefinitions, standardServiceRegistry);
this.managedResources = MetadataBuildingProcess.prepare(metadataSources,
metamodelBuilder.getBootstrapContext());
applyMetadataBuilderContributor();
// BVAL integration:
this.validatorFactory = withValidatorFactory(
buildTimeSettings.get(org.hibernate.cfg.AvailableSettings.JPA_VALIDATION_FACTORY));
// Unable to automatically handle:
// AvailableSettings.ENHANCER_ENABLE_DIRTY_TRACKING,
// AvailableSettings.ENHANCER_ENABLE_LAZY_INITIALIZATION,
// AvailableSettings.ENHANCER_ENABLE_ASSOCIATION_MANAGEMENT
// for the time being we want to revoke access to the temp ClassLoader if one
// was passed
metamodelBuilder.applyTempClassLoader(null);
if (strategy != null && strategy != MultiTenancyStrategy.NONE) {
ssrBuilder.addService(MultiTenantConnectionProvider.class, new HibernateMultiTenantConnectionProvider());
}
this.multiTenancyStrategy = strategy;
}
public FastBootReactiveEntityManagerFactoryBuilder(PrevalidatedQuarkusMetadata metadata, String persistenceUnitName,
StandardServiceRegistry standardServiceRegistry, RuntimeSettings runtimeSettings, Object validatorFactory,
Object cdiBeanManager, MultiTenancyStrategy strategy) {
super(metadata, persistenceUnitName, standardServiceRegistry, runtimeSettings, validatorFactory, cdiBeanManager,
strategy);
}
public MultiTenancyStrategy getMultiTenancyStrategy() {
return sessionFactoryOptions.getMultiTenancyStrategy();
}
@Override
@SuppressWarnings( {"unchecked"})
public MultiTenantConnectionProvider initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
final MultiTenancyStrategy strategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configurationValues );
if ( !strategy.requiresMultiTenantConnectionProvider() ) {
// nothing to do, but given the separate hierarchies have to handle this here.
return null;
}
final Object configValue = configurationValues.get( AvailableSettings.MULTI_TENANT_CONNECTION_PROVIDER );
if ( configValue == null ) {
// if they also specified the data source *name*, then lets assume they want
// DataSourceBasedMultiTenantConnectionProviderImpl
final Object dataSourceConfigValue = configurationValues.get( AvailableSettings.DATASOURCE );
if ( dataSourceConfigValue != null && String.class.isInstance( dataSourceConfigValue ) ) {
return new DataSourceBasedMultiTenantConnectionProviderImpl();
}
return null;
}
if ( MultiTenantConnectionProvider.class.isInstance( configValue ) ) {
return (MultiTenantConnectionProvider) configValue;
}
else {
final Class<MultiTenantConnectionProvider> implClass;
if ( Class.class.isInstance( configValue ) ) {
implClass = (Class) configValue;
}
else {
final String className = configValue.toString();
final ClassLoaderService classLoaderService = registry.getService( ClassLoaderService.class );
try {
implClass = classLoaderService.classForName( className );
}
catch (ClassLoadingException cle) {
log.warn( "Unable to locate specified class [" + className + "]", cle );
throw new ServiceException( "Unable to locate specified multi-tenant connection provider [" + className + "]" );
}
}
try {
return implClass.newInstance();
}
catch (Exception e) {
log.warn( "Unable to instantiate specified class [" + implClass.getName() + "]", e );
throw new ServiceException( "Unable to instantiate specified multi-tenant connection provider [" + implClass.getName() + "]" );
}
}
}
public AbstractSharedSessionContract(SessionFactoryImpl factory, SessionCreationOptions options) {
this.factory = factory;
this.cacheTransactionSync = factory.getCache().getRegionFactory().createTransactionContext( this );
this.flushMode = options.getInitialSessionFlushMode();
this.tenantIdentifier = options.getTenantIdentifier();
if ( MultiTenancyStrategy.NONE == factory.getSettings().getMultiTenancyStrategy() ) {
if ( tenantIdentifier != null ) {
throw new HibernateException( "SessionFactory was not configured for multi-tenancy" );
}
}
else {
if ( tenantIdentifier == null ) {
throw new HibernateException( "SessionFactory configured for multi-tenancy, but no tenant identifier specified" );
}
}
this.interceptor = interpret( options.getInterceptor() );
this.jdbcTimeZone = options.getJdbcTimeZone();
final StatementInspector statementInspector = interpret( options.getStatementInspector() );
this.jdbcSessionContext = new JdbcSessionContextImpl( this, statementInspector );
this.entityNameResolver = new CoordinatingEntityNameResolver( factory, interceptor );
if ( options instanceof SharedSessionCreationOptions && ( (SharedSessionCreationOptions) options ).isTransactionCoordinatorShared() ) {
if ( options.getConnection() != null ) {
throw new SessionException( "Cannot simultaneously share transaction context and specify connection" );
}
this.isTransactionCoordinatorShared = true;
final SharedSessionCreationOptions sharedOptions = (SharedSessionCreationOptions) options;
this.transactionCoordinator = sharedOptions.getTransactionCoordinator();
this.jdbcCoordinator = sharedOptions.getJdbcCoordinator();
// todo : "wrap" the transaction to no-op cmmit/rollback attempts?
this.currentHibernateTransaction = sharedOptions.getTransaction();
if ( sharedOptions.shouldAutoJoinTransactions() ) {
log.debug(
"Session creation specified 'autoJoinTransactions', which is invalid in conjunction " +
"with sharing JDBC connection between sessions; ignoring"
);
autoJoinTransactions = false;
}
if ( sharedOptions.getPhysicalConnectionHandlingMode() != this.jdbcCoordinator.getLogicalConnection().getConnectionHandlingMode() ) {
log.debug(
"Session creation specified 'PhysicalConnectionHandlingMode which is invalid in conjunction " +
"with sharing JDBC connection between sessions; ignoring"
);
}
addSharedSessionTransactionObserver( transactionCoordinator );
}
else {
this.isTransactionCoordinatorShared = false;
this.autoJoinTransactions = options.shouldAutoJoinTransactions();
this.jdbcCoordinator = new JdbcCoordinatorImpl( options.getConnection(), this );
this.transactionCoordinator = factory.getServiceRegistry()
.getService( TransactionCoordinatorBuilder.class )
.buildTransactionCoordinator( jdbcCoordinator, this );
}
exceptionConverter = new ExceptionConverterImpl( this );
}
@Override
public MultiTenancyStrategy getMultiTenancyStrategy() {
return delegate.getMultiTenancyStrategy();
}