some cleanup to DatasourceConnectionProviderImpl and multi-tenant version
Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
parent
47c99d5a31
commit
a59f2ac6c8
|
@ -526,8 +526,9 @@ public interface JdbcSettings extends C3p0Settings, ProxoolSettings, AgroalSetti
|
||||||
/**
|
/**
|
||||||
* @see javax.sql.DataSource
|
* @see javax.sql.DataSource
|
||||||
*
|
*
|
||||||
* @deprecated The JPA-standard {@link #JAKARTA_JTA_DATASOURCE} or {@link #JAKARTA_JTA_DATASOURCE} setting
|
* @deprecated The JPA-standard {@value #JAKARTA_JTA_DATASOURCE} or
|
||||||
* is now preferred.
|
* {@value #JAKARTA_NON_JTA_DATASOURCE} setting are now
|
||||||
|
* preferred.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
String DATASOURCE = "hibernate.connection.datasource";
|
String DATASOURCE = "hibernate.connection.datasource";
|
||||||
|
|
|
@ -12,7 +12,8 @@ import java.util.Map;
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.cfg.JdbcSettings;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||||
import org.hibernate.engine.jdbc.connections.spi.DatabaseConnectionInfo;
|
import org.hibernate.engine.jdbc.connections.spi.DatabaseConnectionInfo;
|
||||||
|
@ -22,13 +23,17 @@ import org.hibernate.service.spi.Configurable;
|
||||||
import org.hibernate.service.spi.InjectService;
|
import org.hibernate.service.spi.InjectService;
|
||||||
import org.hibernate.service.spi.Stoppable;
|
import org.hibernate.service.spi.Stoppable;
|
||||||
|
|
||||||
|
import static org.hibernate.cfg.JdbcSettings.DATASOURCE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link ConnectionProvider} that manages connections from an underlying {@link DataSource}.
|
* A {@link ConnectionProvider} that manages connections from an underlying {@link DataSource}.
|
||||||
* <p>
|
* <p>
|
||||||
* The {@link DataSource} to use may be specified by either:<ul>
|
* The {@link DataSource} to use may be specified by either:<ul>
|
||||||
* <li>injection using {@link #setDataSource}
|
* <li>injection using {@link #setDataSource},
|
||||||
* <li>declaring the {@link DataSource} instance using the {@value Environment#DATASOURCE} config property
|
* <li>passing the {@link DataSource} instance using {@value JdbcSettings#DATASOURCE},
|
||||||
* <li>declaring the JNDI name under which the {@link DataSource} is found via the {@value Environment#DATASOURCE} config property
|
* {@value JdbcSettings#JAKARTA_JTA_DATASOURCE}, or {@value JdbcSettings#JAKARTA_NON_JTA_DATASOURCE}, or
|
||||||
|
* <li>declaring the JNDI name under which the {@link DataSource} is found via {@value JdbcSettings#DATASOURCE},
|
||||||
|
* {@value JdbcSettings#JAKARTA_JTA_DATASOURCE}, or {@value JdbcSettings#JAKARTA_NON_JTA_DATASOURCE}.
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
|
@ -83,7 +88,7 @@ public class DatasourceConnectionProviderImpl implements ConnectionProvider, Con
|
||||||
@Override
|
@Override
|
||||||
public void configure(Map<String, Object> configValues) {
|
public void configure(Map<String, Object> configValues) {
|
||||||
if ( dataSource == null ) {
|
if ( dataSource == null ) {
|
||||||
final Object dataSourceSetting = configValues.get( Environment.DATASOURCE );
|
final Object dataSourceSetting = configValues.get( DATASOURCE );
|
||||||
if ( dataSourceSetting instanceof DataSource ) {
|
if ( dataSourceSetting instanceof DataSource ) {
|
||||||
dataSource = (DataSource) dataSourceSetting;
|
dataSource = (DataSource) dataSourceSetting;
|
||||||
}
|
}
|
||||||
|
@ -91,7 +96,7 @@ public class DatasourceConnectionProviderImpl implements ConnectionProvider, Con
|
||||||
final String dataSourceJndiName = (String) dataSourceSetting;
|
final String dataSourceJndiName = (String) dataSourceSetting;
|
||||||
if ( dataSourceJndiName == null ) {
|
if ( dataSourceJndiName == null ) {
|
||||||
throw new HibernateException(
|
throw new HibernateException(
|
||||||
"DataSource to use was not injected nor specified by [" + Environment.DATASOURCE
|
"DataSource to use was not injected nor specified by [" + DATASOURCE
|
||||||
+ "] configuration property"
|
+ "] configuration property"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -106,8 +111,8 @@ public class DatasourceConnectionProviderImpl implements ConnectionProvider, Con
|
||||||
throw new HibernateException( "Unable to determine appropriate DataSource to use" );
|
throw new HibernateException( "Unable to determine appropriate DataSource to use" );
|
||||||
}
|
}
|
||||||
|
|
||||||
user = (String) configValues.get( Environment.USER );
|
user = (String) configValues.get( AvailableSettings.USER );
|
||||||
pass = (String) configValues.get( Environment.PASS );
|
pass = (String) configValues.get( AvailableSettings.PASS );
|
||||||
useCredentials = user != null || pass != null;
|
useCredentials = user != null || pass != null;
|
||||||
available = true;
|
available = true;
|
||||||
}
|
}
|
||||||
|
@ -150,7 +155,7 @@ public class DatasourceConnectionProviderImpl implements ConnectionProvider, Con
|
||||||
@Override
|
@Override
|
||||||
public String toInfoString() {
|
public String toInfoString() {
|
||||||
return dataSourceJndiName != null
|
return dataSourceJndiName != null
|
||||||
? "\tDatasource JND name [" + dataSourceJndiName + "]"
|
? "\tDatasource JNDI name [" + dataSourceJndiName + "]"
|
||||||
: "\tProvided DataSource";
|
: "\tProvided DataSource";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,19 +22,20 @@ import org.hibernate.service.spi.ServiceRegistryAwareService;
|
||||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
import org.hibernate.service.spi.Stoppable;
|
import org.hibernate.service.spi.Stoppable;
|
||||||
|
|
||||||
|
import static org.hibernate.cfg.JdbcSettings.DATASOURCE;
|
||||||
import static org.hibernate.cfg.MultiTenancySettings.TENANT_IDENTIFIER_TO_USE_FOR_ANY_KEY;
|
import static org.hibernate.cfg.MultiTenancySettings.TENANT_IDENTIFIER_TO_USE_FOR_ANY_KEY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A concrete implementation of the {@link MultiTenantConnectionProvider} contract bases on a number of
|
* A concrete implementation of the {@link MultiTenantConnectionProvider} contract bases on
|
||||||
* reasonable assumptions. We assume that:<ul>
|
* a number of reasonable assumptions. We assume that:<ul>
|
||||||
* <li>
|
* <li>
|
||||||
* The {@link DataSource} instances are all available from JNDI named by the tenant identifier relative
|
* The {@link DataSource} instances are all available from JNDI named by the tenant
|
||||||
* to a single base JNDI context
|
* identifier relative to a single base JNDI context.
|
||||||
* </li>
|
* </li>
|
||||||
* <li>
|
* <li>
|
||||||
* {@value AvailableSettings#DATASOURCE} is a string naming either the {@literal any}
|
* {@value AvailableSettings#DATASOURCE} is a string naming either the {@literal any}
|
||||||
* data source or the base JNDI context. If the latter, {@link MultiTenancySettings#TENANT_IDENTIFIER_TO_USE_FOR_ANY_KEY} must
|
* data source or the base JNDI context. If the latter,
|
||||||
* also be set.
|
* {@link MultiTenancySettings#TENANT_IDENTIFIER_TO_USE_FOR_ANY_KEY} must also be set.
|
||||||
* </li>
|
* </li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
|
@ -44,10 +45,11 @@ public class DataSourceBasedMultiTenantConnectionProviderImpl<T>
|
||||||
extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl<T>
|
extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl<T>
|
||||||
implements ServiceRegistryAwareService, Stoppable {
|
implements ServiceRegistryAwareService, Stoppable {
|
||||||
|
|
||||||
private Map<T, DataSource> dataSourceMap;
|
private final Map<T, DataSource> dataSourceMap = new ConcurrentHashMap<>();
|
||||||
private JndiService jndiService;
|
private JndiService jndiService;
|
||||||
private T tenantIdentifierForAny;
|
private T tenantIdentifierForAny;
|
||||||
private String baseJndiNamespace;
|
private String baseJndiNamespace;
|
||||||
|
private String jndiName;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DataSource selectAnyDataSource() {
|
protected DataSource selectAnyDataSource() {
|
||||||
|
@ -65,21 +67,17 @@ public class DataSourceBasedMultiTenantConnectionProviderImpl<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<T, DataSource> dataSourceMap() {
|
private Map<T, DataSource> dataSourceMap() {
|
||||||
if ( dataSourceMap == null ) {
|
|
||||||
dataSourceMap = new ConcurrentHashMap<>();
|
|
||||||
}
|
|
||||||
return dataSourceMap;
|
return dataSourceMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void injectServices(ServiceRegistryImplementor serviceRegistry) {
|
public void injectServices(ServiceRegistryImplementor serviceRegistry) {
|
||||||
final Object dataSourceConfigValue =
|
final ConfigurationService configurationService = serviceRegistry.requireService( ConfigurationService.class );
|
||||||
serviceRegistry.requireService( ConfigurationService.class )
|
final Object dataSourceConfigValue = configurationService.getSettings().get( DATASOURCE );
|
||||||
.getSettings().get( AvailableSettings.DATASOURCE );
|
|
||||||
if ( !(dataSourceConfigValue instanceof String) ) {
|
if ( !(dataSourceConfigValue instanceof String) ) {
|
||||||
throw new HibernateException( "Improper set up of DataSourceBasedMultiTenantConnectionProviderImpl" );
|
throw new HibernateException( "illegal value for configuration setting '" + DATASOURCE + "'" );
|
||||||
}
|
}
|
||||||
final String jndiName = (String) dataSourceConfigValue;
|
jndiName = (String) dataSourceConfigValue;
|
||||||
|
|
||||||
jndiService = serviceRegistry.getService( JndiService.class );
|
jndiService = serviceRegistry.getService( JndiService.class );
|
||||||
if ( jndiService == null ) {
|
if ( jndiService == null ) {
|
||||||
|
@ -91,17 +89,18 @@ public class DataSourceBasedMultiTenantConnectionProviderImpl<T>
|
||||||
throw new HibernateException( "JNDI name [" + jndiName + "] could not be resolved" );
|
throw new HibernateException( "JNDI name [" + jndiName + "] could not be resolved" );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( namedObject instanceof DataSource ) {
|
if ( namedObject instanceof DataSource datasource ) {
|
||||||
final int loc = jndiName.lastIndexOf( '/' );
|
final int loc = jndiName.lastIndexOf( '/' );
|
||||||
this.baseJndiNamespace = jndiName.substring( 0, loc );
|
baseJndiNamespace = jndiName.substring( 0, loc );
|
||||||
this.tenantIdentifierForAny = (T) jndiName.substring( loc + 1 );
|
final String prefix = jndiName.substring(loc + 1);
|
||||||
dataSourceMap().put( tenantIdentifierForAny, (DataSource) namedObject );
|
tenantIdentifierForAny = (T) prefix;
|
||||||
|
dataSourceMap().put( tenantIdentifierForAny, datasource );
|
||||||
}
|
}
|
||||||
else if ( namedObject instanceof Context ) {
|
else if ( namedObject instanceof Context ) {
|
||||||
this.baseJndiNamespace = jndiName;
|
baseJndiNamespace = jndiName;
|
||||||
this.tenantIdentifierForAny = (T) serviceRegistry.requireService( ConfigurationService.class )
|
final Object configuredTenantId =
|
||||||
.getSettings()
|
configurationService.getSettings().get( TENANT_IDENTIFIER_TO_USE_FOR_ANY_KEY );
|
||||||
.get( TENANT_IDENTIFIER_TO_USE_FOR_ANY_KEY );
|
tenantIdentifierForAny = (T) configuredTenantId;
|
||||||
if ( tenantIdentifierForAny == null ) {
|
if ( tenantIdentifierForAny == null ) {
|
||||||
throw new HibernateException( "JNDI name named a Context, but tenant identifier to use for ANY was not specified" );
|
throw new HibernateException( "JNDI name named a Context, but tenant identifier to use for ANY was not specified" );
|
||||||
}
|
}
|
||||||
|
@ -116,10 +115,7 @@ public class DataSourceBasedMultiTenantConnectionProviderImpl<T>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
if ( dataSourceMap != null ) {
|
dataSourceMap.clear();
|
||||||
dataSourceMap.clear();
|
|
||||||
dataSourceMap = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -139,5 +135,4 @@ public class DataSourceBasedMultiTenantConnectionProviderImpl<T>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,11 +163,12 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
|
||||||
|
|
||||||
private DatabaseConnectionInfo buildDbInfo(ServiceRegistryImplementor registry, Dialect dialect) {
|
private DatabaseConnectionInfo buildDbInfo(ServiceRegistryImplementor registry, Dialect dialect) {
|
||||||
if ( !isMultiTenancyEnabled( registry ) ) {
|
if ( !isMultiTenancyEnabled( registry ) ) {
|
||||||
final ConnectionProvider cp = registry.requireService( ConnectionProvider.class );
|
return registry.requireService( ConnectionProvider.class )
|
||||||
return cp.getDatabaseConnectionInfo( dialect );
|
.getDatabaseConnectionInfo( dialect );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
final MultiTenantConnectionProvider<?> mcp = registry.requireService( MultiTenantConnectionProvider.class );
|
final MultiTenantConnectionProvider<?> mcp =
|
||||||
|
registry.requireService( MultiTenantConnectionProvider.class );
|
||||||
return mcp.getDatabaseConnectionInfo( dialect );
|
return mcp.getDatabaseConnectionInfo( dialect );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue