HHH-5697 - Support for multi-tenancy
This commit is contained in:
parent
98877a3b28
commit
3ff0288da5
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.hibernate.cfg.Environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the methods for multi-tenancy understood by Hibernate.
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public enum MultiTenancyStrategy {
|
||||||
|
/**
|
||||||
|
* Multi-tenancy implemented by use of discriminator columns.
|
||||||
|
*/
|
||||||
|
DISCRIMINATOR,
|
||||||
|
/**
|
||||||
|
* Multi-tenancy implemented as separate schemas.
|
||||||
|
*/
|
||||||
|
SCHEMA,
|
||||||
|
/**
|
||||||
|
* Multi-tenancy implemented as separate databases.
|
||||||
|
*/
|
||||||
|
DATABASE,
|
||||||
|
/**
|
||||||
|
* No multi-tenancy
|
||||||
|
*/
|
||||||
|
NONE;
|
||||||
|
|
||||||
|
public static MultiTenancyStrategy determineMultiTenancyStrategy(Map properties) {
|
||||||
|
final Object strategy = properties.get( Environment.MULTI_TENANT );
|
||||||
|
if ( strategy == null ) {
|
||||||
|
return MultiTenancyStrategy.NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( MultiTenancyStrategy.class.isInstance( strategy ) ) {
|
||||||
|
return (MultiTenancyStrategy) strategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String strategyName = strategy.toString();
|
||||||
|
if ( MultiTenancyStrategy.DISCRIMINATOR.name().equals( strategyName ) ) {
|
||||||
|
return MultiTenancyStrategy.DISCRIMINATOR;
|
||||||
|
}
|
||||||
|
else if ( MultiTenancyStrategy.SCHEMA.name().equals( strategyName ) ) {
|
||||||
|
return MultiTenancyStrategy.SCHEMA;
|
||||||
|
}
|
||||||
|
else if ( MultiTenancyStrategy.DATABASE.name().equals( strategyName ) ) {
|
||||||
|
return MultiTenancyStrategy.DATABASE;
|
||||||
|
}
|
||||||
|
else if ( MultiTenancyStrategy.NONE.name().equals( strategyName ) ) {
|
||||||
|
return MultiTenancyStrategy.NONE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// todo log?
|
||||||
|
return MultiTenancyStrategy.NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,6 +31,24 @@ import java.io.Serializable;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface SharedSessionContract extends Serializable {
|
public interface SharedSessionContract extends Serializable {
|
||||||
|
/**
|
||||||
|
* Obtain the tenant identifier associated with this session.
|
||||||
|
*
|
||||||
|
* @return The tenant identifier associated with this session, or {@code null}
|
||||||
|
*/
|
||||||
|
public String getTenantIdentifier();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should be set only once for the session. Would rather this be supplied to opening the session, as
|
||||||
|
* being discussed for HHH-2860
|
||||||
|
*
|
||||||
|
* @param identifier The tenant identifier.
|
||||||
|
*
|
||||||
|
* @deprecated HHH-2860
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public void setTenantIdentifier(String identifier);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begin a unit of work and return the associated {@link Transaction} object. If a new underlying transaction is
|
* Begin a unit of work and return the associated {@link Transaction} object. If a new underlying transaction is
|
||||||
* required, begin the transaction. Otherwise continue the new work in the context of the existing underlying
|
* required, begin the transaction. Otherwise continue the new work in the context of the existing underlying
|
||||||
|
|
|
@ -551,6 +551,11 @@ public final class Environment {
|
||||||
*/
|
*/
|
||||||
public static final String NON_CONTEXTUAL_LOB_CREATION = "hibernate.jdbc.lob.non_contextual_creation";
|
public static final String NON_CONTEXTUAL_LOB_CREATION = "hibernate.jdbc.lob.non_contextual_creation";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strategy for multi-tenancy.
|
||||||
|
* @see org.hibernate.MultiTenancyStrategy
|
||||||
|
*/
|
||||||
|
public static final String MULTI_TENANT = "hibernate.multiTenancy";
|
||||||
|
|
||||||
private static final BytecodeProvider BYTECODE_PROVIDER_INSTANCE;
|
private static final BytecodeProvider BYTECODE_PROVIDER_INSTANCE;
|
||||||
private static final boolean ENABLE_BINARY_STREAMS;
|
private static final boolean ENABLE_BINARY_STREAMS;
|
||||||
|
|
|
@ -26,6 +26,7 @@ package org.hibernate.cfg;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.hibernate.ConnectionReleaseMode;
|
import org.hibernate.ConnectionReleaseMode;
|
||||||
import org.hibernate.EntityMode;
|
import org.hibernate.EntityMode;
|
||||||
|
import org.hibernate.MultiTenancyStrategy;
|
||||||
import org.hibernate.cache.QueryCacheFactory;
|
import org.hibernate.cache.QueryCacheFactory;
|
||||||
import org.hibernate.cache.RegionFactory;
|
import org.hibernate.cache.RegionFactory;
|
||||||
import org.hibernate.hql.QueryTranslatorFactory;
|
import org.hibernate.hql.QueryTranslatorFactory;
|
||||||
|
@ -81,6 +82,7 @@ public final class Settings {
|
||||||
// private ComponentTuplizerFactory componentTuplizerFactory; todo : HHH-3517 and HHH-1907
|
// private ComponentTuplizerFactory componentTuplizerFactory; todo : HHH-3517 and HHH-1907
|
||||||
// private BytecodeProvider bytecodeProvider;
|
// private BytecodeProvider bytecodeProvider;
|
||||||
private String importFiles;
|
private String importFiles;
|
||||||
|
private MultiTenancyStrategy multiTenancyStrategy;
|
||||||
|
|
||||||
private JtaPlatform jtaPlatform;
|
private JtaPlatform jtaPlatform;
|
||||||
|
|
||||||
|
@ -438,4 +440,12 @@ public final class Settings {
|
||||||
void setJtaPlatform(JtaPlatform jtaPlatform) {
|
void setJtaPlatform(JtaPlatform jtaPlatform) {
|
||||||
this.jtaPlatform = jtaPlatform;
|
this.jtaPlatform = jtaPlatform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MultiTenancyStrategy getMultiTenancyStrategy() {
|
||||||
|
return multiTenancyStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMultiTenancyStrategy(MultiTenancyStrategy multiTenancyStrategy) {
|
||||||
|
this.multiTenancyStrategy = multiTenancyStrategy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.hibernate.ConnectionReleaseMode;
|
||||||
import org.hibernate.EntityMode;
|
import org.hibernate.EntityMode;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.HibernateLogger;
|
import org.hibernate.HibernateLogger;
|
||||||
|
import org.hibernate.MultiTenancyStrategy;
|
||||||
import org.hibernate.cache.QueryCacheFactory;
|
import org.hibernate.cache.QueryCacheFactory;
|
||||||
import org.hibernate.cache.RegionFactory;
|
import org.hibernate.cache.RegionFactory;
|
||||||
import org.hibernate.cache.impl.NoCachingRegionFactory;
|
import org.hibernate.cache.impl.NoCachingRegionFactory;
|
||||||
|
@ -241,6 +242,9 @@ public class SettingsFactory implements Serializable {
|
||||||
LOG.checkNullability(enabledDisabled(checkNullability));
|
LOG.checkNullability(enabledDisabled(checkNullability));
|
||||||
settings.setCheckNullability(checkNullability);
|
settings.setCheckNullability(checkNullability);
|
||||||
|
|
||||||
|
MultiTenancyStrategy multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( properties );
|
||||||
|
LOG.debug( "multi-tenancy strategy : " + multiTenancyStrategy );
|
||||||
|
settings.setMultiTenancyStrategy( multiTenancyStrategy );
|
||||||
|
|
||||||
// String provider = properties.getProperty( Environment.BYTECODE_PROVIDER );
|
// String provider = properties.getProperty( Environment.BYTECODE_PROVIDER );
|
||||||
// log.info( "Bytecode provider name : " + provider );
|
// log.info( "Bytecode provider name : " + provider );
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.hibernate.ConnectionReleaseMode;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.Interceptor;
|
import org.hibernate.Interceptor;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.MultiTenancyStrategy;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
import org.hibernate.SessionFactoryObserver;
|
import org.hibernate.SessionFactoryObserver;
|
||||||
|
@ -52,6 +53,7 @@ import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.proxy.EntityNotFoundDelegate;
|
import org.hibernate.proxy.EntityNotFoundDelegate;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
|
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
|
||||||
|
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
import org.hibernate.type.TypeResolver;
|
import org.hibernate.type.TypeResolver;
|
||||||
|
@ -255,7 +257,7 @@ public interface SessionFactoryImplementor extends Mapping, SessionFactory {
|
||||||
*/
|
*/
|
||||||
public FetchProfile getFetchProfile(String name);
|
public FetchProfile getFetchProfile(String name);
|
||||||
|
|
||||||
public ServiceRegistry getServiceRegistry();
|
public ServiceRegistryImplementor getServiceRegistry();
|
||||||
|
|
||||||
public void addObserver(SessionFactoryObserver observer);
|
public void addObserver(SessionFactoryObserver observer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
* Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
|
||||||
* indicated by the @author tags or express copyright attribution
|
* indicated by the @author tags or express copyright attribution
|
||||||
* statements applied by the authors. All third-party contributions are
|
* statements applied by the authors. All third-party contributions are
|
||||||
* distributed under license by Red Hat Middleware LLC.
|
* distributed under license by Red Hat Inc.
|
||||||
*
|
*
|
||||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
@ -20,7 +20,6 @@
|
||||||
* Free Software Foundation, Inc.
|
* Free Software Foundation, Inc.
|
||||||
* 51 Franklin Street, Fifth Floor
|
* 51 Franklin Street, Fifth Floor
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
package org.hibernate.engine;
|
package org.hibernate.engine;
|
||||||
|
|
||||||
|
@ -39,6 +38,7 @@ import org.hibernate.ScrollMode;
|
||||||
import org.hibernate.ScrollableResults;
|
import org.hibernate.ScrollableResults;
|
||||||
import org.hibernate.collection.PersistentCollection;
|
import org.hibernate.collection.PersistentCollection;
|
||||||
import org.hibernate.engine.jdbc.LobCreationContext;
|
import org.hibernate.engine.jdbc.LobCreationContext;
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
|
||||||
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
|
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
|
||||||
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
|
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
|
||||||
import org.hibernate.event.EventListeners;
|
import org.hibernate.event.EventListeners;
|
||||||
|
@ -47,16 +47,21 @@ import org.hibernate.loader.custom.CustomQuery;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the internal contract between the <tt>Session</tt> and other parts of
|
* Defines the internal contract between {@link org.hibernate.Session} / {@link org.hibernate.StatelessSession} and
|
||||||
* Hibernate such as implementors of <tt>Type</tt> or <tt>EntityPersister</tt>.
|
* other parts of Hibernate such as {@link Type}, {@link EntityPersister} and
|
||||||
|
* {@link org.hibernate.persister.collection.CollectionPersister} implementors
|
||||||
*
|
*
|
||||||
* @see org.hibernate.Session the interface to the application
|
|
||||||
* @see org.hibernate.impl.SessionImpl the actual implementation
|
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface SessionImplementor extends Serializable, LobCreationContext {
|
public interface SessionImplementor extends Serializable, LobCreationContext {
|
||||||
|
/**
|
||||||
|
* Provides access to JDBC connections
|
||||||
|
*
|
||||||
|
* @return The contract for accessing JDBC connections.
|
||||||
|
*/
|
||||||
|
public JdbcConnectionAccess getJdbcConnectionAccess();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the interceptor currently in use by this event source.
|
* Retrieves the interceptor currently in use by this event source.
|
||||||
|
|
|
@ -71,7 +71,8 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator {
|
||||||
this.logicalConnection = new LogicalConnectionImpl(
|
this.logicalConnection = new LogicalConnectionImpl(
|
||||||
userSuppliedConnection,
|
userSuppliedConnection,
|
||||||
transactionCoordinator.getTransactionContext().getConnectionReleaseMode(),
|
transactionCoordinator.getTransactionContext().getConnectionReleaseMode(),
|
||||||
transactionCoordinator.getTransactionContext().getTransactionEnvironment().getJdbcServices()
|
transactionCoordinator.getTransactionContext().getTransactionEnvironment().getJdbcServices(),
|
||||||
|
transactionCoordinator.getTransactionContext().getJdbcConnectionAccess()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,21 +22,28 @@
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
package org.hibernate.engine.jdbc.internal;
|
package org.hibernate.engine.jdbc.internal;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.DatabaseMetaData;
|
import java.sql.DatabaseMetaData;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
import org.hibernate.HibernateLogger;
|
import org.hibernate.HibernateLogger;
|
||||||
|
import org.hibernate.MultiTenancyStrategy;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.jdbc.LobCreationContext;
|
import org.hibernate.engine.jdbc.LobCreationContext;
|
||||||
import org.hibernate.engine.jdbc.LobCreator;
|
import org.hibernate.engine.jdbc.LobCreator;
|
||||||
import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData;
|
import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData;
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
|
||||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
import org.hibernate.engine.jdbc.spi.ResultSetWrapper;
|
import org.hibernate.engine.jdbc.spi.ResultSetWrapper;
|
||||||
import org.hibernate.engine.jdbc.spi.SchemaNameResolver;
|
import org.hibernate.engine.jdbc.spi.SchemaNameResolver;
|
||||||
|
@ -45,41 +52,39 @@ import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
|
||||||
import org.hibernate.internal.util.ReflectHelper;
|
import org.hibernate.internal.util.ReflectHelper;
|
||||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||||
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
|
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
|
||||||
|
import org.hibernate.service.jdbc.connections.spi.MultiTenantConnectionProvider;
|
||||||
import org.hibernate.service.jdbc.dialect.spi.DialectFactory;
|
import org.hibernate.service.jdbc.dialect.spi.DialectFactory;
|
||||||
import org.hibernate.service.spi.Configurable;
|
import org.hibernate.service.spi.Configurable;
|
||||||
import org.hibernate.service.spi.InjectService;
|
import org.hibernate.service.spi.ServiceRegistryAwareService;
|
||||||
import org.jboss.logging.Logger;
|
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard implementation of the {@link JdbcServices} contract
|
* Standard implementation of the {@link JdbcServices} contract
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class JdbcServicesImpl implements JdbcServices, Configurable {
|
public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareService, Configurable {
|
||||||
|
|
||||||
private static final HibernateLogger LOG = Logger.getMessageLogger(HibernateLogger.class, JdbcServicesImpl.class.getName());
|
private static final HibernateLogger LOG = Logger.getMessageLogger(HibernateLogger.class, JdbcServicesImpl.class.getName());
|
||||||
|
|
||||||
private ConnectionProvider connectionProvider;
|
private ServiceRegistryImplementor serviceRegistry;
|
||||||
|
|
||||||
@InjectService
|
|
||||||
public void setConnectionProvider(ConnectionProvider connectionProvider) {
|
|
||||||
this.connectionProvider = connectionProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
private DialectFactory dialectFactory;
|
|
||||||
|
|
||||||
@InjectService
|
|
||||||
public void setDialectFactory(DialectFactory dialectFactory) {
|
|
||||||
this.dialectFactory = dialectFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Dialect dialect;
|
private Dialect dialect;
|
||||||
|
private ConnectionProvider connectionProvider;
|
||||||
private SqlStatementLogger sqlStatementLogger;
|
private SqlStatementLogger sqlStatementLogger;
|
||||||
private SqlExceptionHelper sqlExceptionHelper;
|
private SqlExceptionHelper sqlExceptionHelper;
|
||||||
private ExtractedDatabaseMetaData extractedMetaDataSupport;
|
private ExtractedDatabaseMetaData extractedMetaDataSupport;
|
||||||
private LobCreatorBuilder lobCreatorBuilder;
|
private LobCreatorBuilder lobCreatorBuilder;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void injectServices(ServiceRegistryImplementor serviceRegistry) {
|
||||||
|
this.serviceRegistry = serviceRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void configure(Map configValues) {
|
public void configure(Map configValues) {
|
||||||
|
final JdbcConnectionAccess jdbcConnectionAccess = buildJdbcConnectionAccess( configValues );
|
||||||
|
final DialectFactory dialectFactory = serviceRegistry.getService( DialectFactory.class );
|
||||||
|
|
||||||
Dialect dialect = null;
|
Dialect dialect = null;
|
||||||
LobCreatorBuilder lobCreatorBuilder = null;
|
LobCreatorBuilder lobCreatorBuilder = null;
|
||||||
|
|
||||||
|
@ -105,9 +110,9 @@ public class JdbcServicesImpl implements JdbcServices, Configurable {
|
||||||
boolean useJdbcMetadata = ConfigurationHelper.getBoolean( "hibernate.temp.use_jdbc_metadata_defaults", configValues, true );
|
boolean useJdbcMetadata = ConfigurationHelper.getBoolean( "hibernate.temp.use_jdbc_metadata_defaults", configValues, true );
|
||||||
if ( useJdbcMetadata ) {
|
if ( useJdbcMetadata ) {
|
||||||
try {
|
try {
|
||||||
Connection conn = connectionProvider.getConnection();
|
Connection connection = jdbcConnectionAccess.obtainConnection();
|
||||||
try {
|
try {
|
||||||
DatabaseMetaData meta = conn.getMetaData();
|
DatabaseMetaData meta = connection.getMetaData();
|
||||||
LOG.database(meta.getDatabaseProductName(),
|
LOG.database(meta.getDatabaseProductName(),
|
||||||
meta.getDatabaseProductVersion(),
|
meta.getDatabaseProductVersion(),
|
||||||
meta.getDatabaseMajorVersion(),
|
meta.getDatabaseMajorVersion(),
|
||||||
|
@ -128,25 +133,25 @@ public class JdbcServicesImpl implements JdbcServices, Configurable {
|
||||||
lobLocatorUpdateCopy = meta.locatorsUpdateCopy();
|
lobLocatorUpdateCopy = meta.locatorsUpdateCopy();
|
||||||
typeInfoSet.addAll( TypeInfoExtracter.extractTypeInfo( meta ) );
|
typeInfoSet.addAll( TypeInfoExtracter.extractTypeInfo( meta ) );
|
||||||
|
|
||||||
dialect = dialectFactory.buildDialect( configValues, conn );
|
dialect = dialectFactory.buildDialect( configValues, connection );
|
||||||
|
|
||||||
catalogName = conn.getCatalog();
|
catalogName = connection.getCatalog();
|
||||||
SchemaNameResolver schemaNameResolver = determineExplicitSchemaNameResolver( configValues );
|
SchemaNameResolver schemaNameResolver = determineExplicitSchemaNameResolver( configValues );
|
||||||
if ( schemaNameResolver == null ) {
|
if ( schemaNameResolver == null ) {
|
||||||
// todo : add dialect method
|
// todo : add dialect method
|
||||||
// schemaNameResolver = dialect.getSchemaNameResolver();
|
// schemaNameResolver = dialect.getSchemaNameResolver();
|
||||||
}
|
}
|
||||||
if ( schemaNameResolver != null ) {
|
if ( schemaNameResolver != null ) {
|
||||||
schemaName = schemaNameResolver.resolveSchemaName( conn );
|
schemaName = schemaNameResolver.resolveSchemaName( connection );
|
||||||
}
|
}
|
||||||
lobCreatorBuilder = new LobCreatorBuilder( configValues, conn );
|
lobCreatorBuilder = new LobCreatorBuilder( configValues, connection );
|
||||||
}
|
}
|
||||||
catch ( SQLException sqle ) {
|
catch ( SQLException sqle ) {
|
||||||
LOG.unableToObtainConnectionMetadata(sqle.getMessage());
|
LOG.unableToObtainConnectionMetadata(sqle.getMessage());
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if ( conn != null ) {
|
if ( connection != null ) {
|
||||||
connectionProvider.closeConnection( conn );
|
jdbcConnectionAccess.releaseConnection( connection );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,6 +195,57 @@ public class JdbcServicesImpl implements JdbcServices, Configurable {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JdbcConnectionAccess buildJdbcConnectionAccess(Map configValues) {
|
||||||
|
final MultiTenancyStrategy multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configValues );
|
||||||
|
|
||||||
|
if ( MultiTenancyStrategy.NONE == multiTenancyStrategy ) {
|
||||||
|
connectionProvider = serviceRegistry.getService( ConnectionProvider.class );
|
||||||
|
return new ConnectionProviderJdbcConnectionAccess( connectionProvider );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
connectionProvider = null;
|
||||||
|
final MultiTenantConnectionProvider multiTenantConnectionProvider = serviceRegistry.getService( MultiTenantConnectionProvider.class );
|
||||||
|
return new MultiTenantConnectionProviderJdbcConnectionAccess( multiTenantConnectionProvider );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ConnectionProviderJdbcConnectionAccess implements JdbcConnectionAccess {
|
||||||
|
private final ConnectionProvider connectionProvider;
|
||||||
|
|
||||||
|
public ConnectionProviderJdbcConnectionAccess(ConnectionProvider connectionProvider) {
|
||||||
|
this.connectionProvider = connectionProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Connection obtainConnection() throws SQLException {
|
||||||
|
return connectionProvider.getConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void releaseConnection(Connection connection) throws SQLException {
|
||||||
|
connection.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MultiTenantConnectionProviderJdbcConnectionAccess implements JdbcConnectionAccess {
|
||||||
|
private final MultiTenantConnectionProvider connectionProvider;
|
||||||
|
|
||||||
|
public MultiTenantConnectionProviderJdbcConnectionAccess(MultiTenantConnectionProvider connectionProvider) {
|
||||||
|
this.connectionProvider = connectionProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Connection obtainConnection() throws SQLException {
|
||||||
|
return connectionProvider.getAnyConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void releaseConnection(Connection connection) throws SQLException {
|
||||||
|
connection.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// todo : add to Environment
|
// todo : add to Environment
|
||||||
public static final String SCHEMA_NAME_RESOLVER = "hibernate.schema_name_resolver";
|
public static final String SCHEMA_NAME_RESOLVER = "hibernate.schema_name_resolver";
|
||||||
|
|
||||||
|
@ -220,9 +276,7 @@ public class JdbcServicesImpl implements JdbcServices, Configurable {
|
||||||
|
|
||||||
private Set<String> parseKeywords(String extraKeywordsString) {
|
private Set<String> parseKeywords(String extraKeywordsString) {
|
||||||
Set<String> keywordSet = new HashSet<String>();
|
Set<String> keywordSet = new HashSet<String>();
|
||||||
for ( String keyword : extraKeywordsString.split( "," ) ) {
|
keywordSet.addAll( Arrays.asList( extraKeywordsString.split( "," ) ) );
|
||||||
keywordSet.add( keyword );
|
|
||||||
}
|
|
||||||
return keywordSet;
|
return keywordSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,81 +332,93 @@ public class JdbcServicesImpl implements JdbcServices, Configurable {
|
||||||
this.typeInfoSet = typeInfoSet;
|
this.typeInfoSet = typeInfoSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean supportsScrollableResults() {
|
public boolean supportsScrollableResults() {
|
||||||
return supportsScrollableResults;
|
return supportsScrollableResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean supportsGetGeneratedKeys() {
|
public boolean supportsGetGeneratedKeys() {
|
||||||
return supportsGetGeneratedKeys;
|
return supportsGetGeneratedKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean supportsBatchUpdates() {
|
public boolean supportsBatchUpdates() {
|
||||||
return supportsBatchUpdates;
|
return supportsBatchUpdates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean supportsDataDefinitionInTransaction() {
|
public boolean supportsDataDefinitionInTransaction() {
|
||||||
return supportsDataDefinitionInTransaction;
|
return supportsDataDefinitionInTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean doesDataDefinitionCauseTransactionCommit() {
|
public boolean doesDataDefinitionCauseTransactionCommit() {
|
||||||
return doesDataDefinitionCauseTransactionCommit;
|
return doesDataDefinitionCauseTransactionCommit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Set<String> getExtraKeywords() {
|
public Set<String> getExtraKeywords() {
|
||||||
return extraKeywords;
|
return extraKeywords;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public SQLStateType getSqlStateType() {
|
public SQLStateType getSqlStateType() {
|
||||||
return sqlStateType;
|
return sqlStateType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean doesLobLocatorUpdateCopy() {
|
public boolean doesLobLocatorUpdateCopy() {
|
||||||
return lobLocatorUpdateCopy;
|
return lobLocatorUpdateCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getConnectionSchemaName() {
|
public String getConnectionSchemaName() {
|
||||||
return connectionSchemaName;
|
return connectionSchemaName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getConnectionCatalogName() {
|
public String getConnectionCatalogName() {
|
||||||
return connectionCatalogName;
|
return connectionCatalogName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public LinkedHashSet<TypeInfo> getTypeInfoSet() {
|
public LinkedHashSet<TypeInfo> getTypeInfoSet() {
|
||||||
return typeInfoSet;
|
return typeInfoSet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ConnectionProvider getConnectionProvider() {
|
public ConnectionProvider getConnectionProvider() {
|
||||||
return connectionProvider;
|
return connectionProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public SqlStatementLogger getSqlStatementLogger() {
|
public SqlStatementLogger getSqlStatementLogger() {
|
||||||
return sqlStatementLogger;
|
return sqlStatementLogger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public SqlExceptionHelper getSqlExceptionHelper() {
|
public SqlExceptionHelper getSqlExceptionHelper() {
|
||||||
return sqlExceptionHelper;
|
return sqlExceptionHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Dialect getDialect() {
|
public Dialect getDialect() {
|
||||||
return dialect;
|
return dialect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public ExtractedDatabaseMetaData getExtractedMetaDataSupport() {
|
public ExtractedDatabaseMetaData getExtractedMetaDataSupport() {
|
||||||
return extractedMetaDataSupport;
|
return extractedMetaDataSupport;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public LobCreator getLobCreator(LobCreationContext lobCreationContext) {
|
public LobCreator getLobCreator(LobCreationContext lobCreationContext) {
|
||||||
return lobCreatorBuilder.buildLobCreator( lobCreationContext );
|
return lobCreatorBuilder.buildLobCreator( lobCreationContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public ResultSetWrapper getResultSetWrapper() {
|
public ResultSetWrapper getResultSetWrapper() {
|
||||||
return ResultSetWrapperImpl.INSTANCE;
|
return ResultSetWrapperImpl.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ import org.hibernate.HibernateLogger;
|
||||||
import org.hibernate.JDBCException;
|
import org.hibernate.JDBCException;
|
||||||
import org.hibernate.engine.jdbc.internal.proxy.ProxyBuilder;
|
import org.hibernate.engine.jdbc.internal.proxy.ProxyBuilder;
|
||||||
import org.hibernate.engine.jdbc.spi.ConnectionObserver;
|
import org.hibernate.engine.jdbc.spi.ConnectionObserver;
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
|
||||||
import org.hibernate.engine.jdbc.spi.JdbcResourceRegistry;
|
import org.hibernate.engine.jdbc.spi.JdbcResourceRegistry;
|
||||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
|
import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
|
||||||
|
@ -61,6 +62,7 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
|
||||||
|
|
||||||
private final transient ConnectionReleaseMode connectionReleaseMode;
|
private final transient ConnectionReleaseMode connectionReleaseMode;
|
||||||
private final transient JdbcServices jdbcServices;
|
private final transient JdbcServices jdbcServices;
|
||||||
|
private final transient JdbcConnectionAccess jdbcConnectionAccess;
|
||||||
private final transient JdbcResourceRegistry jdbcResourceRegistry;
|
private final transient JdbcResourceRegistry jdbcResourceRegistry;
|
||||||
private final transient List<ConnectionObserver> observers;
|
private final transient List<ConnectionObserver> observers;
|
||||||
|
|
||||||
|
@ -73,10 +75,12 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
|
||||||
public LogicalConnectionImpl(
|
public LogicalConnectionImpl(
|
||||||
Connection userSuppliedConnection,
|
Connection userSuppliedConnection,
|
||||||
ConnectionReleaseMode connectionReleaseMode,
|
ConnectionReleaseMode connectionReleaseMode,
|
||||||
JdbcServices jdbcServices) {
|
JdbcServices jdbcServices,
|
||||||
|
JdbcConnectionAccess jdbcConnectionAccess) {
|
||||||
this(
|
this(
|
||||||
connectionReleaseMode,
|
connectionReleaseMode,
|
||||||
jdbcServices,
|
jdbcServices,
|
||||||
|
jdbcConnectionAccess,
|
||||||
(userSuppliedConnection != null),
|
(userSuppliedConnection != null),
|
||||||
false,
|
false,
|
||||||
new ArrayList<ConnectionObserver>()
|
new ArrayList<ConnectionObserver>()
|
||||||
|
@ -87,6 +91,7 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
|
||||||
private LogicalConnectionImpl(
|
private LogicalConnectionImpl(
|
||||||
ConnectionReleaseMode connectionReleaseMode,
|
ConnectionReleaseMode connectionReleaseMode,
|
||||||
JdbcServices jdbcServices,
|
JdbcServices jdbcServices,
|
||||||
|
JdbcConnectionAccess jdbcConnectionAccess,
|
||||||
boolean isUserSuppliedConnection,
|
boolean isUserSuppliedConnection,
|
||||||
boolean isClosed,
|
boolean isClosed,
|
||||||
List<ConnectionObserver> observers) {
|
List<ConnectionObserver> observers) {
|
||||||
|
@ -94,6 +99,7 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
|
||||||
jdbcServices, isUserSuppliedConnection, connectionReleaseMode
|
jdbcServices, isUserSuppliedConnection, connectionReleaseMode
|
||||||
);
|
);
|
||||||
this.jdbcServices = jdbcServices;
|
this.jdbcServices = jdbcServices;
|
||||||
|
this.jdbcConnectionAccess = jdbcConnectionAccess;
|
||||||
this.jdbcResourceRegistry = new JdbcResourceRegistryImpl( getJdbcServices().getSqlExceptionHelper() );
|
this.jdbcResourceRegistry = new JdbcResourceRegistryImpl( getJdbcServices().getSqlExceptionHelper() );
|
||||||
this.observers = observers;
|
this.observers = observers;
|
||||||
|
|
||||||
|
@ -286,7 +292,7 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
|
||||||
private void obtainConnection() throws JDBCException {
|
private void obtainConnection() throws JDBCException {
|
||||||
LOG.debugf("Obtaining JDBC connection");
|
LOG.debugf("Obtaining JDBC connection");
|
||||||
try {
|
try {
|
||||||
physicalConnection = getJdbcServices().getConnectionProvider().getConnection();
|
physicalConnection = jdbcConnectionAccess.obtainConnection();
|
||||||
for ( ConnectionObserver observer : observers ) {
|
for ( ConnectionObserver observer : observers ) {
|
||||||
observer.physicalConnectionObtained( physicalConnection );
|
observer.physicalConnectionObtained( physicalConnection );
|
||||||
}
|
}
|
||||||
|
@ -304,13 +310,19 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
|
||||||
*/
|
*/
|
||||||
private void releaseConnection() throws JDBCException {
|
private void releaseConnection() throws JDBCException {
|
||||||
LOG.debugf("Releasing JDBC connection");
|
LOG.debugf("Releasing JDBC connection");
|
||||||
if ( physicalConnection == null ) return;
|
if ( physicalConnection == null ) {
|
||||||
try {
|
return;
|
||||||
if (!physicalConnection.isClosed()) getJdbcServices().getSqlExceptionHelper().logAndClearWarnings(physicalConnection);
|
|
||||||
if (!isUserSuppliedConnection) getJdbcServices().getConnectionProvider().closeConnection(physicalConnection);
|
|
||||||
}
|
}
|
||||||
catch (SQLException sqle) {
|
try {
|
||||||
throw getJdbcServices().getSqlExceptionHelper().convert( sqle, "Could not close connection" );
|
if ( ! physicalConnection.isClosed() ) {
|
||||||
|
getJdbcServices().getSqlExceptionHelper().logAndClearWarnings( physicalConnection );
|
||||||
|
}
|
||||||
|
if ( ! isUserSuppliedConnection ) {
|
||||||
|
jdbcConnectionAccess.releaseConnection( physicalConnection );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
throw getJdbcServices().getSqlExceptionHelper().convert( e, "Could not close connection" );
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
physicalConnection = null;
|
physicalConnection = null;
|
||||||
|
@ -424,6 +436,7 @@ public class LogicalConnectionImpl implements LogicalConnectionImplementor {
|
||||||
return new LogicalConnectionImpl(
|
return new LogicalConnectionImpl(
|
||||||
transactionContext.getConnectionReleaseMode(),
|
transactionContext.getConnectionReleaseMode(),
|
||||||
transactionContext.getTransactionEnvironment().getJdbcServices(),
|
transactionContext.getTransactionEnvironment().getJdbcServices(),
|
||||||
|
transactionContext.getJdbcConnectionAccess(),
|
||||||
isUserSuppliedConnection,
|
isUserSuppliedConnection,
|
||||||
isClosed,
|
isClosed,
|
||||||
observers
|
observers
|
||||||
|
|
|
@ -1,210 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
|
||||||
* indicated by the @author tags or express copyright attribution
|
|
||||||
* statements applied by the authors. All third-party contributions are
|
|
||||||
* distributed under license by Red Hat Inc.
|
|
||||||
*
|
|
||||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
|
||||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
|
||||||
* Lesser General Public License, as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
|
||||||
* for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this distribution; if not, write to:
|
|
||||||
* Free Software Foundation, Inc.
|
|
||||||
* 51 Franklin Street, Fifth Floor
|
|
||||||
* Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package org.hibernate.engine.jdbc.spi;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.sql.CallableStatement;
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
import org.hibernate.ScrollMode;
|
|
||||||
import org.hibernate.jdbc.Expectation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encapsulates JDBC Connection management SPI.
|
|
||||||
* <p/>
|
|
||||||
* The lifecycle is intended to span a logical series of interactions with the
|
|
||||||
* database. Internally, this means the the lifecycle of the Session.
|
|
||||||
*
|
|
||||||
* @author Gail Badner
|
|
||||||
*/
|
|
||||||
public interface ConnectionManager extends Serializable {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the connection currently managed by this ConnectionManager.
|
|
||||||
* <p/>
|
|
||||||
* Note, that we may need to obtain a connection to return here if a
|
|
||||||
* connection has either not yet been obtained (non-UserSuppliedConnectionProvider)
|
|
||||||
* or has previously been aggressively released (if supported in this environment).
|
|
||||||
*
|
|
||||||
* @return The current Connection.
|
|
||||||
*
|
|
||||||
* @throws HibernateException Indicates a connection is currently not
|
|
||||||
* available (we are currently manually disconnected).
|
|
||||||
*/
|
|
||||||
Connection getConnection();
|
|
||||||
|
|
||||||
// TODO: should this be removd from the SPI?
|
|
||||||
boolean hasBorrowedConnection();
|
|
||||||
|
|
||||||
// TODO: should this be removd from the SPI?
|
|
||||||
void releaseBorrowedConnection();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this ConnectionManager instance "logically" connected. Meaning
|
|
||||||
* do we either have a cached connection available or do we have the
|
|
||||||
* ability to obtain a connection on demand.
|
|
||||||
*
|
|
||||||
* @return True if logically connected; false otherwise.
|
|
||||||
*/
|
|
||||||
boolean isCurrentlyConnected();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* To be called after execution of each JDBC statement. Used to
|
|
||||||
* conditionally release the JDBC connection aggressively if
|
|
||||||
* the configured release mode indicates.
|
|
||||||
*/
|
|
||||||
void afterStatement();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the transaction timeout.
|
|
||||||
* @param seconds - number of seconds until the the transaction times out.
|
|
||||||
*/
|
|
||||||
void setTransactionTimeout(int seconds);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* To be called after Session completion. Used to release the JDBC
|
|
||||||
* connection.
|
|
||||||
*
|
|
||||||
* @return The connection mantained here at time of close. Null if
|
|
||||||
* there was no connection cached internally.
|
|
||||||
*/
|
|
||||||
Connection close();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manually disconnect the underlying JDBC Connection. The assumption here
|
|
||||||
* is that the manager will be reconnected at a later point in time.
|
|
||||||
*
|
|
||||||
* @return The connection mantained here at time of disconnect. Null if
|
|
||||||
* there was no connection cached internally.
|
|
||||||
*/
|
|
||||||
Connection manualDisconnect();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manually reconnect the underlying JDBC Connection. Should be called at
|
|
||||||
* some point after manualDisconnect().
|
|
||||||
* <p/>
|
|
||||||
* This form is used for ConnectionProvider-supplied connections.
|
|
||||||
*/
|
|
||||||
void manualReconnect();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manually reconnect the underlying JDBC Connection. Should be called at
|
|
||||||
* some point after manualDisconnect().
|
|
||||||
* <p/>
|
|
||||||
* This form is used for user-supplied connections.
|
|
||||||
*/
|
|
||||||
void manualReconnect(Connection suppliedConnection);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback to let us know that a flush is beginning. We use this fact
|
|
||||||
* to temporarily circumvent aggressive connection releasing until after
|
|
||||||
* the flush cycle is complete {@link #flushEnding()}
|
|
||||||
*/
|
|
||||||
void flushBeginning();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback to let us know that a flush is ending. We use this fact to
|
|
||||||
* stop circumventing aggressive releasing connections.
|
|
||||||
*/
|
|
||||||
void flushEnding();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a non-batchable prepared statement to use for inserting / deleting / updating,
|
|
||||||
* using JDBC3 getGeneratedKeys ({@link java.sql.Connection#prepareStatement(String, int)}).
|
|
||||||
* <p/>
|
|
||||||
* If not explicitly closed via {@link java.sql.PreparedStatement#close()}, it will be
|
|
||||||
* released when the session is closed or disconnected.
|
|
||||||
*/
|
|
||||||
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a non-batchable prepared statement to use for inserting / deleting / updating.
|
|
||||||
* using JDBC3 getGeneratedKeys ({@link java.sql.Connection#prepareStatement(String, String[])}).
|
|
||||||
* <p/>
|
|
||||||
* If not explicitly closed via {@link java.sql.PreparedStatement#close()}, it will be
|
|
||||||
* released when the session is closed or disconnected.
|
|
||||||
*/
|
|
||||||
public PreparedStatement prepareStatement(String sql, String[] columnNames);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a non-batchable prepared statement to use for selecting. Does not
|
|
||||||
* result in execution of the current batch.
|
|
||||||
* <p/>
|
|
||||||
* If not explicitly closed via {@link java.sql.PreparedStatement#close()},
|
|
||||||
* it will be released when the session is closed or disconnected.
|
|
||||||
*/
|
|
||||||
public PreparedStatement prepareSelectStatement(String sql);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a non-batchable prepared statement to use for inserting / deleting / updating.
|
|
||||||
* <p/>
|
|
||||||
* If not explicitly closed via {@link java.sql.PreparedStatement#close()}, it will be
|
|
||||||
* released when the session is closed or disconnected.
|
|
||||||
*/
|
|
||||||
public PreparedStatement prepareStatement(String sql, boolean isCallable);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a non-batchable callable statement to use for inserting / deleting / updating.
|
|
||||||
* <p/>
|
|
||||||
* If not explicitly closed via {@link java.sql.PreparedStatement#close()}, it will be
|
|
||||||
* released when the session is closed or disconnected.
|
|
||||||
*/
|
|
||||||
public CallableStatement prepareCallableStatement(String sql);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a batchable prepared statement to use for inserting / deleting / updating
|
|
||||||
* (might be called many times before a single call to <tt>executeBatch()</tt>).
|
|
||||||
* After setting parameters, call <tt>addToBatch</tt> - do not execute the
|
|
||||||
* statement explicitly.
|
|
||||||
* @see org.hibernate.engine.jdbc.batch.spi.Batch#addToBatch
|
|
||||||
* <p/>
|
|
||||||
* If not explicitly closed via {@link java.sql.PreparedStatement#close()}, it will be
|
|
||||||
* released when the session is closed or disconnected.
|
|
||||||
*/
|
|
||||||
public PreparedStatement prepareBatchStatement(Object key, String sql, boolean isCallable);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a prepared statement for use in loading / querying. Does not
|
|
||||||
* result in execution of the current batch.
|
|
||||||
* <p/>
|
|
||||||
* If not explicitly closed via {@link java.sql.PreparedStatement#close()},
|
|
||||||
* it will be released when the session is closed or disconnected.
|
|
||||||
*/
|
|
||||||
public PreparedStatement prepareQueryStatement(
|
|
||||||
String sql,
|
|
||||||
boolean isScrollable,
|
|
||||||
ScrollMode scrollMode,
|
|
||||||
boolean isCallable);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancel the current query statement
|
|
||||||
*/
|
|
||||||
public void cancelLastQuery();
|
|
||||||
|
|
||||||
public void abortBatch();
|
|
||||||
|
|
||||||
public void addToBatch(Object batchKey, String sql, Expectation expectation);
|
|
||||||
|
|
||||||
public void executeBatch();
|
|
||||||
}
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.engine.jdbc.spi;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides centralized access to JDBC connections. Centralized to hide the complexity of accounting for contextual
|
||||||
|
* (multi-tenant) versus non-contextual access.
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface JdbcConnectionAccess extends Serializable {
|
||||||
|
public Connection obtainConnection() throws SQLException;
|
||||||
|
public void releaseConnection(Connection connection) throws SQLException;
|
||||||
|
}
|
|
@ -24,6 +24,7 @@
|
||||||
package org.hibernate.engine.transaction.spi;
|
package org.hibernate.engine.transaction.spi;
|
||||||
|
|
||||||
import org.hibernate.ConnectionReleaseMode;
|
import org.hibernate.ConnectionReleaseMode;
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@ -110,4 +111,6 @@ public interface TransactionContext extends Serializable {
|
||||||
public void beforeTransactionCompletion(TransactionImplementor hibernateTransaction);
|
public void beforeTransactionCompletion(TransactionImplementor hibernateTransaction);
|
||||||
|
|
||||||
public void afterTransactionCompletion(TransactionImplementor hibernateTransaction, boolean successful);
|
public void afterTransactionCompletion(TransactionImplementor hibernateTransaction, boolean successful);
|
||||||
|
|
||||||
|
public JdbcConnectionAccess getJdbcConnectionAccess();
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,11 +30,13 @@ import java.sql.SQLException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.MultiTenancyStrategy;
|
||||||
import org.hibernate.Query;
|
import org.hibernate.Query;
|
||||||
import org.hibernate.SQLQuery;
|
import org.hibernate.SQLQuery;
|
||||||
import org.hibernate.ScrollableResults;
|
import org.hibernate.ScrollableResults;
|
||||||
import org.hibernate.SessionException;
|
import org.hibernate.SessionException;
|
||||||
import org.hibernate.SharedSessionContract;
|
import org.hibernate.SharedSessionContract;
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
|
||||||
import org.hibernate.engine.NamedQueryDefinition;
|
import org.hibernate.engine.NamedQueryDefinition;
|
||||||
import org.hibernate.engine.NamedSQLQueryDefinition;
|
import org.hibernate.engine.NamedSQLQueryDefinition;
|
||||||
import org.hibernate.engine.QueryParameters;
|
import org.hibernate.engine.QueryParameters;
|
||||||
|
@ -48,6 +50,8 @@ import org.hibernate.engine.transaction.spi.TransactionContext;
|
||||||
import org.hibernate.engine.transaction.spi.TransactionEnvironment;
|
import org.hibernate.engine.transaction.spi.TransactionEnvironment;
|
||||||
import org.hibernate.jdbc.WorkExecutor;
|
import org.hibernate.jdbc.WorkExecutor;
|
||||||
import org.hibernate.jdbc.WorkExecutorVisitable;
|
import org.hibernate.jdbc.WorkExecutorVisitable;
|
||||||
|
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
|
||||||
|
import org.hibernate.service.jdbc.connections.spi.MultiTenantConnectionProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Functionality common to stateless and stateful sessions
|
* Functionality common to stateless and stateful sessions
|
||||||
|
@ -57,6 +61,7 @@ import org.hibernate.jdbc.WorkExecutorVisitable;
|
||||||
public abstract class AbstractSessionImpl implements Serializable, SharedSessionContract, SessionImplementor, TransactionContext {
|
public abstract class AbstractSessionImpl implements Serializable, SharedSessionContract, SessionImplementor, TransactionContext {
|
||||||
|
|
||||||
protected transient SessionFactoryImpl factory;
|
protected transient SessionFactoryImpl factory;
|
||||||
|
private String tenantIdentifier;
|
||||||
private boolean closed = false;
|
private boolean closed = false;
|
||||||
|
|
||||||
protected AbstractSessionImpl(SessionFactoryImpl factory) {
|
protected AbstractSessionImpl(SessionFactoryImpl factory) {
|
||||||
|
@ -203,4 +208,77 @@ public abstract class AbstractSessionImpl implements Serializable, SharedSession
|
||||||
return scrollCustomQuery( getNativeSQLQueryPlan( spec ).getCustomQuery(), queryParameters );
|
return scrollCustomQuery( getNativeSQLQueryPlan( spec ).getCustomQuery(), queryParameters );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTenantIdentifier() {
|
||||||
|
return tenantIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTenantIdentifier(String identifier) {
|
||||||
|
if ( MultiTenancyStrategy.NONE == factory.getSettings().getMultiTenancyStrategy() ) {
|
||||||
|
throw new HibernateException( "SessionFactory was not configured for multi-tenancy" );
|
||||||
|
}
|
||||||
|
this.tenantIdentifier = identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
private transient JdbcConnectionAccess jdbcConnectionAccess;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JdbcConnectionAccess getJdbcConnectionAccess() {
|
||||||
|
if ( jdbcConnectionAccess == null ) {
|
||||||
|
if ( MultiTenancyStrategy.NONE == factory.getSettings().getMultiTenancyStrategy() ) {
|
||||||
|
jdbcConnectionAccess = new NonContextualJdbcConnectionAccess(
|
||||||
|
factory.getServiceRegistry().getService( ConnectionProvider.class )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
jdbcConnectionAccess = new ContextualJdbcConnectionAccess(
|
||||||
|
factory.getServiceRegistry().getService( MultiTenantConnectionProvider.class )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jdbcConnectionAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class NonContextualJdbcConnectionAccess implements JdbcConnectionAccess, Serializable {
|
||||||
|
private final ConnectionProvider connectionProvider;
|
||||||
|
|
||||||
|
private NonContextualJdbcConnectionAccess(ConnectionProvider connectionProvider) {
|
||||||
|
this.connectionProvider = connectionProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Connection obtainConnection() throws SQLException {
|
||||||
|
return connectionProvider.getConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void releaseConnection(Connection connection) throws SQLException {
|
||||||
|
connectionProvider.closeConnection( connection );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ContextualJdbcConnectionAccess implements JdbcConnectionAccess, Serializable {
|
||||||
|
private final MultiTenantConnectionProvider connectionProvider;
|
||||||
|
|
||||||
|
private ContextualJdbcConnectionAccess(MultiTenantConnectionProvider connectionProvider) {
|
||||||
|
this.connectionProvider = connectionProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Connection obtainConnection() throws SQLException {
|
||||||
|
if ( tenantIdentifier == null ) {
|
||||||
|
throw new HibernateException( "Tenant identifier required!" );
|
||||||
|
}
|
||||||
|
return connectionProvider.getConnection( tenantIdentifier );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void releaseConnection(Connection connection) throws SQLException {
|
||||||
|
if ( tenantIdentifier == null ) {
|
||||||
|
throw new HibernateException( "Tenant identifier required!" );
|
||||||
|
}
|
||||||
|
connectionProvider.releaseConnection( tenantIdentifier, connection );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ import org.hibernate.HibernateException;
|
||||||
import org.hibernate.HibernateLogger;
|
import org.hibernate.HibernateLogger;
|
||||||
import org.hibernate.Interceptor;
|
import org.hibernate.Interceptor;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.MultiTenancyStrategy;
|
||||||
import org.hibernate.ObjectNotFoundException;
|
import org.hibernate.ObjectNotFoundException;
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
|
@ -212,6 +213,7 @@ public final class SessionFactoryImpl
|
||||||
this.properties = new Properties();
|
this.properties = new Properties();
|
||||||
this.properties.putAll( cfg.getProperties() );
|
this.properties.putAll( cfg.getProperties() );
|
||||||
this.interceptor = cfg.getInterceptor();
|
this.interceptor = cfg.getInterceptor();
|
||||||
|
|
||||||
this.serviceRegistry = serviceRegistry.getService( SessionFactoryServiceRegistryFactory.class ).buildServiceRegistry(
|
this.serviceRegistry = serviceRegistry.getService( SessionFactoryServiceRegistryFactory.class ).buildServiceRegistry(
|
||||||
this,
|
this,
|
||||||
cfg
|
cfg
|
||||||
|
@ -1260,10 +1262,11 @@ public final class SessionFactoryImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServiceRegistry getServiceRegistry() {
|
public ServiceRegistryImplementor getServiceRegistry() {
|
||||||
return serviceRegistry;
|
return serviceRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public EntityNotFoundDelegate getEntityNotFoundDelegate() {
|
public EntityNotFoundDelegate getEntityNotFoundDelegate() {
|
||||||
return entityNotFoundDelegate;
|
return entityNotFoundDelegate;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ import org.hibernate.persister.spi.PersisterClassResolver;
|
||||||
import org.hibernate.persister.spi.PersisterFactory;
|
import org.hibernate.persister.spi.PersisterFactory;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
import org.hibernate.service.spi.ServiceRegistryAwareService;
|
import org.hibernate.service.spi.ServiceRegistryAwareService;
|
||||||
|
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
@ -75,10 +76,10 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi
|
||||||
SessionFactoryImplementor.class
|
SessionFactoryImplementor.class
|
||||||
};
|
};
|
||||||
|
|
||||||
private ServiceRegistry serviceRegistry;
|
private ServiceRegistryImplementor serviceRegistry;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void injectServices(ServiceRegistry serviceRegistry) {
|
public void injectServices(ServiceRegistryImplementor serviceRegistry) {
|
||||||
this.serviceRegistry = serviceRegistry;
|
this.serviceRegistry = serviceRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.hibernate.persister.internal.PersisterFactoryInitiator;
|
||||||
import org.hibernate.service.classloading.internal.ClassLoaderServiceInitiator;
|
import org.hibernate.service.classloading.internal.ClassLoaderServiceInitiator;
|
||||||
import org.hibernate.service.internal.SessionFactoryServiceRegistryFactoryInitiator;
|
import org.hibernate.service.internal.SessionFactoryServiceRegistryFactoryInitiator;
|
||||||
import org.hibernate.service.jdbc.connections.internal.ConnectionProviderInitiator;
|
import org.hibernate.service.jdbc.connections.internal.ConnectionProviderInitiator;
|
||||||
|
import org.hibernate.service.jdbc.connections.internal.MultiTenantConnectionProviderInitiator;
|
||||||
import org.hibernate.service.jdbc.dialect.internal.DialectFactoryInitiator;
|
import org.hibernate.service.jdbc.dialect.internal.DialectFactoryInitiator;
|
||||||
import org.hibernate.service.jdbc.dialect.internal.DialectResolverInitiator;
|
import org.hibernate.service.jdbc.dialect.internal.DialectResolverInitiator;
|
||||||
import org.hibernate.service.jmx.internal.JmxServiceInitiator;
|
import org.hibernate.service.jmx.internal.JmxServiceInitiator;
|
||||||
|
@ -58,6 +59,7 @@ public class StandardServiceInitiators {
|
||||||
serviceInitiators.add( PersisterFactoryInitiator.INSTANCE );
|
serviceInitiators.add( PersisterFactoryInitiator.INSTANCE );
|
||||||
|
|
||||||
serviceInitiators.add( ConnectionProviderInitiator.INSTANCE );
|
serviceInitiators.add( ConnectionProviderInitiator.INSTANCE );
|
||||||
|
serviceInitiators.add( MultiTenantConnectionProviderInitiator.INSTANCE );
|
||||||
serviceInitiators.add( DialectResolverInitiator.INSTANCE );
|
serviceInitiators.add( DialectResolverInitiator.INSTANCE );
|
||||||
serviceInitiators.add( DialectFactoryInitiator.INSTANCE );
|
serviceInitiators.add( DialectFactoryInitiator.INSTANCE );
|
||||||
serviceInitiators.add( BatchBuilderInitiator.INSTANCE );
|
serviceInitiators.add( BatchBuilderInitiator.INSTANCE );
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||||
* indicated by the @author tags or express copyright attribution
|
* indicated by the @author tags or express copyright attribution
|
||||||
* statements applied by the authors. All third-party contributions are
|
* statements applied by the authors. All third-party contributions are
|
||||||
* distributed under license by Red Hat Inc.
|
* distributed under license by Red Hat Inc.
|
||||||
|
@ -125,12 +125,12 @@ public class BasicServiceRegistryImpl extends AbstractServiceRegistryImpl implem
|
||||||
protected <T extends Service> void configureService(T service) {
|
protected <T extends Service> void configureService(T service) {
|
||||||
applyInjections( service );
|
applyInjections( service );
|
||||||
|
|
||||||
if ( Configurable.class.isInstance( service ) ) {
|
|
||||||
( (Configurable) service ).configure( configurationValues );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ServiceRegistryAwareService.class.isInstance( service ) ) {
|
if ( ServiceRegistryAwareService.class.isInstance( service ) ) {
|
||||||
( (ServiceRegistryAwareService) service ).injectServices( this );
|
( (ServiceRegistryAwareService) service ).injectServices( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( Configurable.class.isInstance( service ) ) {
|
||||||
|
( (Configurable) service ).configure( configurationValues );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ import org.jboss.logging.Logger;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.HibernateLogger;
|
import org.hibernate.HibernateLogger;
|
||||||
|
import org.hibernate.MultiTenancyStrategy;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.internal.util.beans.BeanInfoHelper;
|
import org.hibernate.internal.util.beans.BeanInfoHelper;
|
||||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||||
|
@ -100,6 +101,10 @@ public class ConnectionProviderInitiator implements BasicServiceInitiator<Connec
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConnectionProvider initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
|
public ConnectionProvider initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
|
||||||
|
if ( MultiTenancyStrategy.determineMultiTenancyStrategy( configurationValues ) != MultiTenancyStrategy.NONE ) {
|
||||||
|
// nothing to do, but given the separate hierarchies have to handle this here.
|
||||||
|
}
|
||||||
|
|
||||||
final ClassLoaderService classLoaderService = registry.getService( ClassLoaderService.class );
|
final ClassLoaderService classLoaderService = registry.getService( ClassLoaderService.class );
|
||||||
|
|
||||||
ConnectionProvider connectionProvider = null;
|
ConnectionProvider connectionProvider = null;
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.service.jdbc.connections.internal;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.hibernate.MultiTenancyStrategy;
|
||||||
|
import org.hibernate.service.jdbc.connections.spi.MultiTenantConnectionProvider;
|
||||||
|
import org.hibernate.service.spi.BasicServiceInitiator;
|
||||||
|
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class MultiTenantConnectionProviderInitiator implements BasicServiceInitiator<MultiTenantConnectionProvider> {
|
||||||
|
public static final MultiTenantConnectionProviderInitiator INSTANCE = new MultiTenantConnectionProviderInitiator();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<MultiTenantConnectionProvider> getServiceInitiated() {
|
||||||
|
return MultiTenantConnectionProvider.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MultiTenantConnectionProvider initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
|
||||||
|
if ( MultiTenancyStrategy.determineMultiTenancyStrategy( configurationValues ) == MultiTenancyStrategy.NONE ) {
|
||||||
|
// nothing to do, but given the separate hierarchies have to handle this here.
|
||||||
|
}
|
||||||
|
|
||||||
|
// for now...
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.service.jdbc.connections.spi;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.hibernate.service.UnknownUnwrapTypeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public abstract class AbstractMultiTenantConnectionProvider implements MultiTenantConnectionProvider {
|
||||||
|
protected abstract ConnectionProvider getAnyConnectionProvider();
|
||||||
|
protected abstract ConnectionProvider selectConnectionProvider(String tenantIdentifier);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Connection getAnyConnection() throws SQLException {
|
||||||
|
return getAnyConnectionProvider().getConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void releaseAnyConnection(Connection connection) throws SQLException {
|
||||||
|
getAnyConnectionProvider().closeConnection( connection );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Connection getConnection(String tenantIdentifier) throws SQLException {
|
||||||
|
return selectConnectionProvider( tenantIdentifier ).getConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
|
||||||
|
selectConnectionProvider( tenantIdentifier ).getConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsAggressiveRelease() {
|
||||||
|
return getAnyConnectionProvider().supportsAggressiveRelease();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUnwrappableAs(Class unwrapType) {
|
||||||
|
return ConnectionProvider.class.equals( unwrapType ) ||
|
||||||
|
MultiTenantConnectionProvider.class.equals( unwrapType ) ||
|
||||||
|
AbstractMultiTenantConnectionProvider.class.isAssignableFrom( unwrapType );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings( {"unchecked"})
|
||||||
|
public <T> T unwrap(Class<T> unwrapType) {
|
||||||
|
if ( isUnwrappableAs( unwrapType ) ) {
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new UnknownUnwrapTypeException( unwrapType );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.service.jdbc.connections.spi;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.hibernate.service.Service;
|
||||||
|
import org.hibernate.service.spi.Wrapped;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface MultiTenantConnectionProvider extends Service, Wrapped {
|
||||||
|
/**
|
||||||
|
* Allows access to the database metadata of the underlying database(s) in situations where we do not have a
|
||||||
|
* tenant id (like startup processing, for example).
|
||||||
|
*
|
||||||
|
* @return The database metadata.
|
||||||
|
*
|
||||||
|
* @throws SQLException Indicates a problem opening a connection
|
||||||
|
*/
|
||||||
|
public Connection getAnyConnection() throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release a connection obtained from {@link #getAnyConnection}
|
||||||
|
*
|
||||||
|
* @param connection The JDBC connection to release
|
||||||
|
*
|
||||||
|
* @throws SQLException Indicates a problem closing the connection
|
||||||
|
*/
|
||||||
|
public void releaseAnyConnection(Connection connection) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a connection for Hibernate use according to the underlying strategy of this provider.
|
||||||
|
*
|
||||||
|
* @param tenantIdentifier The identifier of the tenant for which to get a connection
|
||||||
|
*
|
||||||
|
* @return The obtained JDBC connection
|
||||||
|
*
|
||||||
|
* @throws SQLException Indicates a problem opening a connection
|
||||||
|
* @throws org.hibernate.HibernateException Indicates a problem otherwise obtaining a connection.
|
||||||
|
*/
|
||||||
|
public Connection getConnection(String tenantIdentifier) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release a connection from Hibernate use.
|
||||||
|
*
|
||||||
|
* @param connection The JDBC connection to release
|
||||||
|
* @param tenantIdentifier The identifier of the tenant.
|
||||||
|
*
|
||||||
|
* @throws SQLException Indicates a problem closing the connection
|
||||||
|
* @throws org.hibernate.HibernateException Indicates a problem otherwise releasing a connection.
|
||||||
|
*/
|
||||||
|
public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does this connection provider support aggressive release of JDBC
|
||||||
|
* connections and re-acquisition of those connections (if need be) later?
|
||||||
|
* <p/>
|
||||||
|
* This is used in conjunction with {@link org.hibernate.cfg.Environment#RELEASE_CONNECTIONS}
|
||||||
|
* to aggressively release JDBC connections. However, the configured ConnectionProvider
|
||||||
|
* must support re-acquisition of the same underlying connection for that semantic to work.
|
||||||
|
* <p/>
|
||||||
|
* Typically, this is only true in managed environments where a container
|
||||||
|
* tracks connections by transaction or thread.
|
||||||
|
*
|
||||||
|
* Note that JTA semantic depends on the fact that the underlying connection provider does
|
||||||
|
* support aggressive release.
|
||||||
|
*
|
||||||
|
* @return {@code true} if aggressive releasing is supported; {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
public boolean supportsAggressiveRelease();
|
||||||
|
}
|
|
@ -29,6 +29,7 @@ import org.hibernate.service.jta.platform.spi.JtaPlatform;
|
||||||
import org.hibernate.service.spi.Configurable;
|
import org.hibernate.service.spi.Configurable;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
import org.hibernate.service.spi.ServiceRegistryAwareService;
|
import org.hibernate.service.spi.ServiceRegistryAwareService;
|
||||||
|
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
|
|
||||||
import javax.transaction.Synchronization;
|
import javax.transaction.Synchronization;
|
||||||
import javax.transaction.SystemException;
|
import javax.transaction.SystemException;
|
||||||
|
@ -44,10 +45,10 @@ public abstract class AbstractJtaPlatform
|
||||||
implements JtaPlatform, Configurable, ServiceRegistryAwareService, TransactionManagerAccess {
|
implements JtaPlatform, Configurable, ServiceRegistryAwareService, TransactionManagerAccess {
|
||||||
private boolean cacheTransactionManager;
|
private boolean cacheTransactionManager;
|
||||||
private boolean cacheUserTransaction;
|
private boolean cacheUserTransaction;
|
||||||
private ServiceRegistry serviceRegistry;
|
private ServiceRegistryImplementor serviceRegistry;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void injectServices(ServiceRegistry serviceRegistry) {
|
public void injectServices(ServiceRegistryImplementor serviceRegistry) {
|
||||||
this.serviceRegistry = serviceRegistry;
|
this.serviceRegistry = serviceRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,6 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.service.spi;
|
package org.hibernate.service.spi;
|
||||||
|
|
||||||
import org.hibernate.service.ServiceRegistry;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows services to be injected with the {@link org.hibernate.service.ServiceRegistry} during configuration phase.
|
* Allows services to be injected with the {@link org.hibernate.service.ServiceRegistry} during configuration phase.
|
||||||
*
|
*
|
||||||
|
@ -36,5 +34,5 @@ public interface ServiceRegistryAwareService {
|
||||||
*
|
*
|
||||||
* @param serviceRegistry The registry
|
* @param serviceRegistry The registry
|
||||||
*/
|
*/
|
||||||
public void injectServices(ServiceRegistry serviceRegistry);
|
public void injectServices(ServiceRegistryImplementor serviceRegistry);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ import java.sql.SQLException;
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
interface ConnectionHelper {
|
public interface ConnectionHelper {
|
||||||
/**
|
/**
|
||||||
* Prepare the helper for use.
|
* Prepare the helper for use.
|
||||||
*
|
*
|
||||||
|
|
|
@ -157,6 +157,17 @@ public class SchemaExport {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SchemaExport(
|
||||||
|
ConnectionHelper connectionHelper,
|
||||||
|
String[] dropSql,
|
||||||
|
String[] createSql) {
|
||||||
|
this.connectionHelper = connectionHelper;
|
||||||
|
this.dropSQL = dropSql;
|
||||||
|
this.createSQL = createSql;
|
||||||
|
this.importFiles = "";
|
||||||
|
this.formatter = FormatStyle.DDL.getFormatter();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For generating a export script file, this is the file which will be written.
|
* For generating a export script file, this is the file which will be written.
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.common;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
|
||||||
|
import org.hibernate.engine.transaction.spi.TransactionEnvironment;
|
||||||
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class JdbcConnectionAccessImpl implements JdbcConnectionAccess {
|
||||||
|
private final ConnectionProvider connectionProvider;
|
||||||
|
|
||||||
|
public JdbcConnectionAccessImpl(TransactionEnvironment transactionEnvironment) {
|
||||||
|
this( transactionEnvironment.getSessionFactory().getServiceRegistry() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public JdbcConnectionAccessImpl(ConnectionProvider connectionProvider) {
|
||||||
|
this.connectionProvider = connectionProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JdbcConnectionAccessImpl(ServiceRegistry serviceRegistry) {
|
||||||
|
this( serviceRegistry.getService( ConnectionProvider.class ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Connection obtainConnection() throws SQLException {
|
||||||
|
return connectionProvider.getConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void releaseConnection(Connection connection) throws SQLException {
|
||||||
|
connectionProvider.closeConnection( connection );
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,18 +24,30 @@
|
||||||
package org.hibernate.test.common;
|
package org.hibernate.test.common;
|
||||||
|
|
||||||
import org.hibernate.ConnectionReleaseMode;
|
import org.hibernate.ConnectionReleaseMode;
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
|
||||||
import org.hibernate.engine.transaction.spi.TransactionContext;
|
import org.hibernate.engine.transaction.spi.TransactionContext;
|
||||||
import org.hibernate.engine.transaction.spi.TransactionEnvironment;
|
import org.hibernate.engine.transaction.spi.TransactionEnvironment;
|
||||||
import org.hibernate.engine.transaction.spi.TransactionImplementor;
|
import org.hibernate.engine.transaction.spi.TransactionImplementor;
|
||||||
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class TransactionContextImpl implements TransactionContext {
|
public class TransactionContextImpl implements TransactionContext {
|
||||||
private final TransactionEnvironment transactionEnvironment;
|
private final TransactionEnvironment transactionEnvironment;
|
||||||
|
private final JdbcConnectionAccess jdbcConnectionAccess;
|
||||||
|
|
||||||
|
public TransactionContextImpl(TransactionEnvironment transactionEnvironment, JdbcConnectionAccess jdbcConnectionAccess) {
|
||||||
|
this.transactionEnvironment = transactionEnvironment;
|
||||||
|
this.jdbcConnectionAccess = jdbcConnectionAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TransactionContextImpl(TransactionEnvironment transactionEnvironment, ServiceRegistry serviceRegistry) {
|
||||||
|
this( transactionEnvironment, new JdbcConnectionAccessImpl( serviceRegistry ) );
|
||||||
|
}
|
||||||
|
|
||||||
public TransactionContextImpl(TransactionEnvironment transactionEnvironment) {
|
public TransactionContextImpl(TransactionEnvironment transactionEnvironment) {
|
||||||
this.transactionEnvironment = transactionEnvironment;
|
this( transactionEnvironment, new JdbcConnectionAccessImpl( transactionEnvironment.getJdbcServices().getConnectionProvider() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -48,6 +60,11 @@ public class TransactionContextImpl implements TransactionContext {
|
||||||
return transactionEnvironment.getTransactionFactory().getDefaultReleaseMode();
|
return transactionEnvironment.getTransactionFactory().getDefaultReleaseMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JdbcConnectionAccess getJdbcConnectionAccess() {
|
||||||
|
return jdbcConnectionAccess;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldAutoJoinTransaction() {
|
public boolean shouldAutoJoinTransaction() {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -38,6 +38,7 @@ import org.junit.Test;
|
||||||
|
|
||||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||||
import org.hibernate.test.common.BasicTestingJdbcServiceImpl;
|
import org.hibernate.test.common.BasicTestingJdbcServiceImpl;
|
||||||
|
import org.hibernate.test.common.JdbcConnectionAccessImpl;
|
||||||
import org.hibernate.test.common.JournalingConnectionObserver;
|
import org.hibernate.test.common.JournalingConnectionObserver;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
@ -112,7 +113,12 @@ public class AggressiveReleaseTest extends BaseUnitTestCase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBasicRelease() {
|
public void testBasicRelease() {
|
||||||
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_STATEMENT, services );
|
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
|
||||||
|
null,
|
||||||
|
ConnectionReleaseMode.AFTER_STATEMENT,
|
||||||
|
services ,
|
||||||
|
new JdbcConnectionAccessImpl( services.getConnectionProvider() )
|
||||||
|
);
|
||||||
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
|
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
|
||||||
JournalingConnectionObserver observer = new JournalingConnectionObserver();
|
JournalingConnectionObserver observer = new JournalingConnectionObserver();
|
||||||
logicalConnection.addObserver( observer );
|
logicalConnection.addObserver( observer );
|
||||||
|
@ -142,7 +148,12 @@ public class AggressiveReleaseTest extends BaseUnitTestCase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReleaseCircumventedByHeldResources() {
|
public void testReleaseCircumventedByHeldResources() {
|
||||||
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_STATEMENT, services );
|
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
|
||||||
|
null,
|
||||||
|
ConnectionReleaseMode.AFTER_STATEMENT,
|
||||||
|
services,
|
||||||
|
new JdbcConnectionAccessImpl( services.getConnectionProvider() )
|
||||||
|
);
|
||||||
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
|
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
|
||||||
JournalingConnectionObserver observer = new JournalingConnectionObserver();
|
JournalingConnectionObserver observer = new JournalingConnectionObserver();
|
||||||
logicalConnection.addObserver( observer );
|
logicalConnection.addObserver( observer );
|
||||||
|
@ -196,7 +207,12 @@ public class AggressiveReleaseTest extends BaseUnitTestCase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReleaseCircumventedManually() {
|
public void testReleaseCircumventedManually() {
|
||||||
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_STATEMENT, services );
|
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
|
||||||
|
null,
|
||||||
|
ConnectionReleaseMode.AFTER_STATEMENT,
|
||||||
|
services,
|
||||||
|
new JdbcConnectionAccessImpl( services.getConnectionProvider() )
|
||||||
|
);
|
||||||
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
|
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
|
||||||
JournalingConnectionObserver observer = new JournalingConnectionObserver();
|
JournalingConnectionObserver observer = new JournalingConnectionObserver();
|
||||||
logicalConnection.addObserver( observer );
|
logicalConnection.addObserver( observer );
|
||||||
|
|
|
@ -41,6 +41,7 @@ import org.hibernate.JDBCException;
|
||||||
import org.hibernate.engine.jdbc.internal.LogicalConnectionImpl;
|
import org.hibernate.engine.jdbc.internal.LogicalConnectionImpl;
|
||||||
import org.hibernate.engine.jdbc.internal.proxy.ProxyBuilder;
|
import org.hibernate.engine.jdbc.internal.proxy.ProxyBuilder;
|
||||||
import org.hibernate.test.common.BasicTestingJdbcServiceImpl;
|
import org.hibernate.test.common.BasicTestingJdbcServiceImpl;
|
||||||
|
import org.hibernate.test.common.JdbcConnectionAccessImpl;
|
||||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,7 +65,8 @@ public class BasicConnectionProxyTest extends BaseUnitTestCase {
|
||||||
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
|
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
|
||||||
null,
|
null,
|
||||||
ConnectionReleaseMode.AFTER_TRANSACTION,
|
ConnectionReleaseMode.AFTER_TRANSACTION,
|
||||||
services
|
services,
|
||||||
|
new JdbcConnectionAccessImpl( services.getConnectionProvider() )
|
||||||
);
|
);
|
||||||
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
|
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
|
||||||
try {
|
try {
|
||||||
|
@ -92,7 +94,8 @@ public class BasicConnectionProxyTest extends BaseUnitTestCase {
|
||||||
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
|
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
|
||||||
null,
|
null,
|
||||||
ConnectionReleaseMode.AFTER_TRANSACTION,
|
ConnectionReleaseMode.AFTER_TRANSACTION,
|
||||||
services
|
services,
|
||||||
|
new JdbcConnectionAccessImpl( services.getConnectionProvider() )
|
||||||
);
|
);
|
||||||
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
|
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
|
||||||
try {
|
try {
|
||||||
|
@ -114,7 +117,8 @@ public class BasicConnectionProxyTest extends BaseUnitTestCase {
|
||||||
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
|
LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl(
|
||||||
null,
|
null,
|
||||||
ConnectionReleaseMode.AFTER_TRANSACTION,
|
ConnectionReleaseMode.AFTER_TRANSACTION,
|
||||||
services
|
services,
|
||||||
|
new JdbcConnectionAccessImpl( services.getConnectionProvider() )
|
||||||
);
|
);
|
||||||
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
|
Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection );
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,9 @@ public class BatchingTest extends BaseUnitTestCase implements BatchKey {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNonBatchingUsage() throws Exception {
|
public void testNonBatchingUsage() throws Exception {
|
||||||
final TransactionContext transactionContext = new TransactionContextImpl( new TransactionEnvironmentImpl( serviceRegistry ) );
|
final TransactionContext transactionContext = new TransactionContextImpl(
|
||||||
|
new TransactionEnvironmentImpl( serviceRegistry )
|
||||||
|
);
|
||||||
|
|
||||||
TransactionCoordinatorImpl transactionCoordinator = new TransactionCoordinatorImpl( null, transactionContext );
|
TransactionCoordinatorImpl transactionCoordinator = new TransactionCoordinatorImpl( null, transactionContext );
|
||||||
JournalingTransactionObserver observer = new JournalingTransactionObserver();
|
JournalingTransactionObserver observer = new JournalingTransactionObserver();
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.multitenancy.schema;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Customer {
|
||||||
|
private Long id;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public Customer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Customer(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,206 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.multitenancy.schema;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.MultiTenancyStrategy;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.SessionFactory;
|
||||||
|
import org.hibernate.cfg.Configuration;
|
||||||
|
import org.hibernate.cfg.Environment;
|
||||||
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
import org.hibernate.service.internal.BasicServiceRegistryImpl;
|
||||||
|
import org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
|
||||||
|
import org.hibernate.service.jdbc.connections.spi.AbstractMultiTenantConnectionProvider;
|
||||||
|
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
|
||||||
|
import org.hibernate.service.jdbc.connections.spi.MultiTenantConnectionProvider;
|
||||||
|
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
|
import org.hibernate.tool.hbm2ddl.ConnectionHelper;
|
||||||
|
import org.hibernate.tool.hbm2ddl.SchemaExport;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.hibernate.testing.env.ConnectionProviderBuilder;
|
||||||
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
|
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class SchemaBasedMultiTenancyTest extends BaseUnitTestCase {
|
||||||
|
private DriverManagerConnectionProviderImpl acmeProvider;
|
||||||
|
private DriverManagerConnectionProviderImpl jbossProvider;
|
||||||
|
|
||||||
|
private ServiceRegistryImplementor serviceRegistry;
|
||||||
|
|
||||||
|
private SessionFactory sessionFactory;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
acmeProvider = ConnectionProviderBuilder.buildConnectionProvider( "acme" );
|
||||||
|
jbossProvider = ConnectionProviderBuilder.buildConnectionProvider( "jboss" );
|
||||||
|
AbstractMultiTenantConnectionProvider multiTenantConnectionProvider = new AbstractMultiTenantConnectionProvider() {
|
||||||
|
@Override
|
||||||
|
protected ConnectionProvider getAnyConnectionProvider() {
|
||||||
|
return acmeProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ConnectionProvider selectConnectionProvider(String tenantIdentifier) {
|
||||||
|
if ( "acme".equals( tenantIdentifier ) ) {
|
||||||
|
return acmeProvider;
|
||||||
|
}
|
||||||
|
else if ( "jboss".equals( tenantIdentifier ) ) {
|
||||||
|
return jbossProvider;
|
||||||
|
}
|
||||||
|
throw new HibernateException( "Unknown tenant identifier" );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Configuration cfg = new Configuration();
|
||||||
|
cfg.getProperties().put( Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE );
|
||||||
|
cfg.addAnnotatedClass( Customer.class );
|
||||||
|
|
||||||
|
cfg.buildMappings();
|
||||||
|
|
||||||
|
// do the acme export
|
||||||
|
new SchemaExport(
|
||||||
|
new ConnectionHelper() {
|
||||||
|
private Connection connection;
|
||||||
|
@Override
|
||||||
|
public void prepare(boolean needsAutoCommit) throws SQLException {
|
||||||
|
connection = acmeProvider.getConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Connection getConnection() throws SQLException {
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void release() throws SQLException {
|
||||||
|
acmeProvider.closeConnection( connection );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cfg.generateDropSchemaScript( ConnectionProviderBuilder.getCorrespondingDialect() ),
|
||||||
|
cfg.generateSchemaCreationScript( ConnectionProviderBuilder.getCorrespondingDialect() )
|
||||||
|
).execute( // so stupid...
|
||||||
|
false, // do not script the export (write it to file)
|
||||||
|
true, // do run it against the database
|
||||||
|
false, // do not *just* perform the drop
|
||||||
|
false // do not *just* perform the create
|
||||||
|
);
|
||||||
|
|
||||||
|
// do the jboss export
|
||||||
|
new SchemaExport(
|
||||||
|
new ConnectionHelper() {
|
||||||
|
private Connection connection;
|
||||||
|
@Override
|
||||||
|
public void prepare(boolean needsAutoCommit) throws SQLException {
|
||||||
|
connection = jbossProvider.getConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Connection getConnection() throws SQLException {
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void release() throws SQLException {
|
||||||
|
jbossProvider.closeConnection( connection );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cfg.generateDropSchemaScript( ConnectionProviderBuilder.getCorrespondingDialect() ),
|
||||||
|
cfg.generateSchemaCreationScript( ConnectionProviderBuilder.getCorrespondingDialect() )
|
||||||
|
).execute( // so stupid...
|
||||||
|
false, // do not script the export (write it to file)
|
||||||
|
true, // do run it against the database
|
||||||
|
false, // do not *just* perform the drop
|
||||||
|
false // do not *just* perform the create
|
||||||
|
);
|
||||||
|
|
||||||
|
serviceRegistry = new BasicServiceRegistryImpl( cfg.getProperties() );
|
||||||
|
serviceRegistry.registerService( MultiTenantConnectionProvider.class, multiTenantConnectionProvider );
|
||||||
|
|
||||||
|
sessionFactory = cfg.buildSessionFactory( serviceRegistry );
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
if ( sessionFactory != null ) {
|
||||||
|
sessionFactory.close();
|
||||||
|
}
|
||||||
|
if ( serviceRegistry != null ) {
|
||||||
|
serviceRegistry.destroy();
|
||||||
|
}
|
||||||
|
if ( jbossProvider != null ) {
|
||||||
|
jbossProvider.stop();
|
||||||
|
}
|
||||||
|
if ( acmeProvider != null ) {
|
||||||
|
acmeProvider.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Session openSession() {
|
||||||
|
return sessionFactory.openSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBasicExpectedBehavior() {
|
||||||
|
Session session = openSession();
|
||||||
|
session.setTenantIdentifier( "jboss" );
|
||||||
|
session.beginTransaction();
|
||||||
|
Customer steve = new Customer( "steve" );
|
||||||
|
session.save( steve );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
|
||||||
|
session = openSession();
|
||||||
|
try {
|
||||||
|
session.setTenantIdentifier( "acme" );
|
||||||
|
session.beginTransaction();
|
||||||
|
Customer check = (Customer) session.get( Customer.class, steve.getId() );
|
||||||
|
Assert.assertNull( "tenancy not properly isolated", check );
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
session = openSession();
|
||||||
|
session.setTenantIdentifier( "jboss" );
|
||||||
|
session.beginTransaction();
|
||||||
|
session.delete( steve );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -29,7 +29,6 @@ import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.dialect.H2Dialect;
|
import org.hibernate.dialect.H2Dialect;
|
||||||
import org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
|
import org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
|
||||||
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the JDBC connection information (currently H2) used by Hibernate for unit (not functional!) tests
|
* Defines the JDBC connection information (currently H2) used by Hibernate for unit (not functional!) tests
|
||||||
|
@ -38,24 +37,36 @@ import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
|
||||||
*/
|
*/
|
||||||
public class ConnectionProviderBuilder {
|
public class ConnectionProviderBuilder {
|
||||||
public static final String DRIVER = "org.h2.Driver";
|
public static final String DRIVER = "org.h2.Driver";
|
||||||
public static final String URL = "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE";
|
public static final String URL = "jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1;MVCC=TRUE";
|
||||||
public static final String USER = "sa";
|
public static final String USER = "sa";
|
||||||
public static final String PASS = "";
|
public static final String PASS = "";
|
||||||
|
|
||||||
public static Properties getConnectionProviderProperties() {
|
public static Properties getConnectionProviderProperties(String dbName) {
|
||||||
Properties props = new Properties( null );
|
Properties props = new Properties( null );
|
||||||
props.put( Environment.DRIVER, DRIVER );
|
props.put( Environment.DRIVER, DRIVER );
|
||||||
props.put( Environment.URL, URL );
|
props.put( Environment.URL, String.format( URL, dbName ) );
|
||||||
props.put( Environment.USER, USER );
|
props.put( Environment.USER, USER );
|
||||||
|
props.put( Environment.PASS, PASS );
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ConnectionProvider buildConnectionProvider() {
|
public static Properties getConnectionProviderProperties() {
|
||||||
|
return getConnectionProviderProperties( "db1" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DriverManagerConnectionProviderImpl buildConnectionProvider() {
|
||||||
return buildConnectionProvider( false );
|
return buildConnectionProvider( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ConnectionProvider buildConnectionProvider(final boolean allowAggressiveRelease) {
|
public static DriverManagerConnectionProviderImpl buildConnectionProvider(String dbName) {
|
||||||
final Properties props = getConnectionProviderProperties();
|
return buildConnectionProvider( getConnectionProviderProperties( dbName ), false );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DriverManagerConnectionProviderImpl buildConnectionProvider(final boolean allowAggressiveRelease) {
|
||||||
|
return buildConnectionProvider( getConnectionProviderProperties( "db1" ), allowAggressiveRelease );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DriverManagerConnectionProviderImpl buildConnectionProvider(Properties props, final boolean allowAggressiveRelease) {
|
||||||
DriverManagerConnectionProviderImpl connectionProvider = new DriverManagerConnectionProviderImpl() {
|
DriverManagerConnectionProviderImpl connectionProvider = new DriverManagerConnectionProviderImpl() {
|
||||||
public boolean supportsAggressiveRelease() {
|
public boolean supportsAggressiveRelease() {
|
||||||
return allowAggressiveRelease;
|
return allowAggressiveRelease;
|
||||||
|
|
Loading…
Reference in New Issue