HHH-7472 - Introduce a "schema management" service

This commit is contained in:
Steve Ebersole 2012-07-28 17:47:04 -05:00
parent 47f6360225
commit 2d82a57632
56 changed files with 1462 additions and 1009 deletions

View File

@ -640,4 +640,6 @@ public interface AvailableSettings {
* @since 5.0
*/
public static final String SCHEMA_MANAGEMENT_TOOL = "hibernate.schema_management_tool";
// todo : add to Environment
String SCHEMA_NAME_RESOLVER = "hibernate.schema_name_resolver";
}

View File

@ -38,7 +38,7 @@ import org.hibernate.cache.internal.RegionFactoryInitiator;
import org.hibernate.cache.internal.StandardQueryCacheFactory;
import org.hibernate.cache.spi.QueryCacheFactory;
import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData;
import org.hibernate.service.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.transaction.spi.TransactionFactory;
import org.hibernate.hql.spi.QueryTranslatorFactory;

View File

@ -1,202 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.env.internal;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.engine.jdbc.env.spi.SchemaCatalogSupport;
import org.hibernate.engine.jdbc.env.spi.StandardSchemaCatalogSupportImpl;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.exception.internal.SQLExceptionTypeDelegate;
import org.hibernate.exception.internal.SQLStateConversionDelegate;
import org.hibernate.exception.internal.StandardSQLExceptionConverter;
import org.hibernate.exception.spi.SQLExceptionConverter;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.service.schema.spi.ExistingSequenceMetadataExtractor;
/**
* @author Steve Ebersole
*/
public class JdbcEnvironmentImpl implements JdbcEnvironment {
private final Dialect dialect;
private final IdentifierHelper identifierHelper;
private final Identifier currentCatalog;
private final Identifier currentSchema;
private final SchemaCatalogSupport schemaCatalogSupport;
private ExistingSequenceMetadataExtractor sequenceMetadataExtractor;
private final Set<String> reservedWords;
private final SqlExceptionHelper sqlExceptionHelper;
public JdbcEnvironmentImpl(DatabaseMetaData dbmd, Dialect dialect, Map properties) throws SQLException {
this.dialect = dialect;
Set<String> reservedWords = new HashSet<String>();
reservedWords.addAll( dialect.getKeywords() );
// todo : do we need to explicitly handle SQL:2003 keywords?
reservedWords.addAll( Arrays.asList( dbmd.getSQLKeywords().split( "," ) ) );
this.reservedWords = reservedWords;
this.identifierHelper = new NormalizingIdentifierHelperImpl(
this,
dbmd.storesMixedCaseQuotedIdentifiers(),
dbmd.storesLowerCaseQuotedIdentifiers(),
dbmd.storesUpperCaseQuotedIdentifiers(),
dbmd.storesUpperCaseIdentifiers(),
dbmd.storesLowerCaseIdentifiers()
);
String currentCatalogName = dbmd.getConnection().getCatalog();
if ( currentCatalogName != null ) {
// intentionally using fromMetaDataObjectName rather than fromMetaDataCatalogName !!!
currentCatalog = identifierHelper.fromMetaDataObjectName( currentCatalogName );
}
else {
currentCatalogName = (String) properties.get( AvailableSettings.DEFAULT_CATALOG );
currentCatalog = Identifier.toIdentifier( currentCatalogName );
}
String currentSchemaName = TemporarySchemaNameResolver.INSTANCE.resolveSchemaName( dbmd.getConnection() );
if ( currentSchemaName != null ) {
// intentionally using fromMetaDataObjectName rather than fromMetaDataSchemaName !!!
currentSchema = identifierHelper.fromMetaDataObjectName( currentSchemaName );
}
else {
currentSchemaName = (String) properties.get( AvailableSettings.DEFAULT_SCHEMA );
currentSchema = Identifier.toIdentifier( currentSchemaName );
}
schemaCatalogSupport = new StandardSchemaCatalogSupportImpl(
dbmd.getCatalogSeparator(),
dbmd.isCatalogAtStart(),
dialect.openQuote(),
dialect.closeQuote()
);
SQLExceptionConverter sqlExceptionConverter = dialect.buildSQLExceptionConverter();
if ( sqlExceptionConverter == null ) {
final StandardSQLExceptionConverter converter = new StandardSQLExceptionConverter();
sqlExceptionConverter = converter;
converter.addDelegate( dialect.buildSQLExceptionConversionDelegate() );
converter.addDelegate( new SQLExceptionTypeDelegate( dialect ) );
converter.addDelegate( new SQLStateConversionDelegate( dialect ) );
}
this.sqlExceptionHelper = new SqlExceptionHelper( sqlExceptionConverter );
this.sequenceMetadataExtractor = new TemporaryExistingSequenceMetadataExtractor( this );
}
public JdbcEnvironmentImpl(Dialect dialect, Map properties) {
this.dialect = dialect;
Set<String> reservedWords = new HashSet<String>();
reservedWords.addAll( dialect.getKeywords() );
// todo : do we need to explicitly handle SQL:2003 keywords?
this.reservedWords = reservedWords;
// again, a simple temporary impl that works on H2
this.identifierHelper = new NormalizingIdentifierHelperImpl(
this,
true, // storesMixedCaseQuotedIdentifiers
false, // storesLowerCaseQuotedIdentifiers
false, // storesUpperCaseQuotedIdentifiers
true, // storesUpperCaseIdentifiers
false // storesLowerCaseIdentifiers
);
String currentCatalogName = (String) properties.get( AvailableSettings.DEFAULT_CATALOG );
currentCatalog = Identifier.toIdentifier( currentCatalogName );
String currentSchemaName = (String) properties.get( AvailableSettings.DEFAULT_SCHEMA );
currentSchema = Identifier.toIdentifier( currentSchemaName );
// again, a simple temporary impl that works on H2
schemaCatalogSupport = new StandardSchemaCatalogSupportImpl(
".",
true,
dialect.openQuote(),
dialect.closeQuote()
);
SQLExceptionConverter sqlExceptionConverter = dialect.buildSQLExceptionConverter();
if ( sqlExceptionConverter == null ) {
final StandardSQLExceptionConverter converter = new StandardSQLExceptionConverter();
sqlExceptionConverter = converter;
converter.addDelegate( dialect.buildSQLExceptionConversionDelegate() );
converter.addDelegate( new SQLExceptionTypeDelegate( dialect ) );
converter.addDelegate( new SQLStateConversionDelegate( dialect ) );
}
this.sqlExceptionHelper = new SqlExceptionHelper( sqlExceptionConverter );
this.sequenceMetadataExtractor = new TemporaryExistingSequenceMetadataExtractor( this );
}
@Override
public Dialect getDialect() {
return dialect;
}
@Override
public Identifier getCurrentCatalog() {
return currentCatalog;
}
@Override
public Identifier getCurrentSchema() {
return currentSchema;
}
@Override
public SchemaCatalogSupport getSchemaCatalogSupport() {
return schemaCatalogSupport;
}
@Override
public IdentifierHelper getIdentifierHelper() {
return identifierHelper;
}
@Override
public Set<String> getReservedWords() {
return reservedWords;
}
@Override
public SqlExceptionHelper getSqlExceptionHelper() {
return sqlExceptionHelper;
}
@Override
public ExistingSequenceMetadataExtractor getExistingSequenceMetadataExtractor() {
return sequenceMetadataExtractor;
}
}

View File

@ -1 +0,0 @@
package org.hibernate.engine.jdbc.env;

View File

@ -1,55 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.env.spi;
import java.util.Set;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.service.schema.spi.ExistingSequenceMetadataExtractor;
/**
* Initial look at this concept we keep talking about with merging information from {@link java.sql.DatabaseMetaData}
* and {@link org.hibernate.dialect.Dialect}
*
* @author Steve Ebersole
*/
public interface JdbcEnvironment {
public Dialect getDialect();
public Identifier getCurrentCatalog();
public Identifier getCurrentSchema();
public SchemaCatalogSupport getSchemaCatalogSupport();
public IdentifierHelper getIdentifierHelper();
public Set<String> getReservedWords();
public SqlExceptionHelper getSqlExceptionHelper();
public ExistingSequenceMetadataExtractor getExistingSequenceMetadataExtractor();
}

View File

@ -23,43 +23,20 @@
*/
package org.hibernate.engine.jdbc.internal;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.jboss.logging.Logger;
import org.hibernate.MultiTenancyStrategy;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
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.ResultSetWrapper;
import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
import org.hibernate.exception.internal.SQLExceptionTypeDelegate;
import org.hibernate.exception.internal.SQLStateConversionDelegate;
import org.hibernate.exception.internal.StandardSQLExceptionConverter;
import org.hibernate.exception.spi.SQLExceptionConverter;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.service.jdbc.connections.spi.MultiTenantConnectionProvider;
import org.hibernate.service.jdbc.cursor.internal.StandardRefCursorSupport;
import org.hibernate.service.jdbc.dialect.spi.DialectFactory;
import org.hibernate.service.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.spi.Configurable;
import org.hibernate.service.spi.ServiceRegistryAwareService;
import org.hibernate.service.spi.ServiceRegistryImplementor;
@ -70,16 +47,11 @@ import org.hibernate.service.spi.ServiceRegistryImplementor;
* @author Steve Ebersole
*/
public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareService, Configurable {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, JdbcServicesImpl.class.getName());
private ServiceRegistryImplementor serviceRegistry;
private JdbcEnvironment jdbcEnvironment;
private Dialect dialect;
private ConnectionProvider connectionProvider;
private SqlStatementLogger sqlStatementLogger;
private SqlExceptionHelper sqlExceptionHelper;
private ExtractedDatabaseMetaData extractedMetaDataSupport;
private LobCreatorBuilder lobCreatorBuilder;
@Override
public void injectServices(ServiceRegistryImplementor serviceRegistry) {
@ -88,359 +60,13 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi
@Override
public void configure(Map configValues) {
final JdbcConnectionAccess jdbcConnectionAccess = buildJdbcConnectionAccess( configValues );
final DialectFactory dialectFactory = serviceRegistry.getService( DialectFactory.class );
this.jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
Dialect dialect = null;
LobCreatorBuilder lobCreatorBuilder = null;
boolean metaSupportsRefCursors = false;
boolean metaSupportsNamedParams = false;
boolean metaSupportsScrollable = false;
boolean metaSupportsGetGeneratedKeys = false;
boolean metaSupportsBatchUpdates = false;
boolean metaReportsDDLCausesTxnCommit = false;
boolean metaReportsDDLInTxnSupported = true;
String extraKeywordsString = "";
int sqlStateType = -1;
boolean lobLocatorUpdateCopy = false;
String catalogName = null;
String schemaName = null;
LinkedHashSet<TypeInfo> typeInfoSet = new LinkedHashSet<TypeInfo>();
// 'hibernate.temp.use_jdbc_metadata_defaults' is a temporary magic value.
// The need for it is intended to be alleviated with future development, thus it is
// not defined as an Environment constant...
//
// it is used to control whether we should consult the JDBC metadata to determine
// certain Settings default values; it is useful to *not* do this when the database
// may not be available (mainly in tools usage).
boolean useJdbcMetadata = ConfigurationHelper.getBoolean( "hibernate.temp.use_jdbc_metadata_defaults", configValues, true );
if ( useJdbcMetadata ) {
try {
Connection connection = jdbcConnectionAccess.obtainConnection();
try {
DatabaseMetaData meta = connection.getMetaData();
if(LOG.isDebugEnabled()) {
LOG.debugf( "Database ->\n" + " name : %s\n" + " version : %s\n" + " major : %s\n" + " minor : %s",
meta.getDatabaseProductName(),
meta.getDatabaseProductVersion(),
meta.getDatabaseMajorVersion(),
meta.getDatabaseMinorVersion()
);
LOG.debugf( "Driver ->\n" + " name : %s\n" + " version : %s\n" + " major : %s\n" + " minor : %s",
meta.getDriverName(),
meta.getDriverVersion(),
meta.getDriverMajorVersion(),
meta.getDriverMinorVersion()
);
LOG.debugf( "JDBC version : %s.%s", meta.getJDBCMajorVersion(), meta.getJDBCMinorVersion() );
}
metaSupportsRefCursors = StandardRefCursorSupport.supportsRefCursors( meta );
metaSupportsNamedParams = meta.supportsNamedParameters();
metaSupportsScrollable = meta.supportsResultSetType( ResultSet.TYPE_SCROLL_INSENSITIVE );
metaSupportsBatchUpdates = meta.supportsBatchUpdates();
metaReportsDDLCausesTxnCommit = meta.dataDefinitionCausesTransactionCommit();
metaReportsDDLInTxnSupported = !meta.dataDefinitionIgnoredInTransactions();
metaSupportsGetGeneratedKeys = meta.supportsGetGeneratedKeys();
extraKeywordsString = meta.getSQLKeywords();
sqlStateType = meta.getSQLStateType();
lobLocatorUpdateCopy = meta.locatorsUpdateCopy();
typeInfoSet.addAll( TypeInfoExtracter.extractTypeInfo( meta ) );
dialect = dialectFactory.buildDialect( configValues, connection );
catalogName = connection.getCatalog();
SchemaNameResolver schemaNameResolver = determineExplicitSchemaNameResolver( configValues );
if ( schemaNameResolver == null ) {
// todo : add dialect method
// schemaNameResolver = dialect.getSchemaNameResolver();
}
if ( schemaNameResolver != null ) {
schemaName = schemaNameResolver.resolveSchemaName( connection );
}
lobCreatorBuilder = new LobCreatorBuilder( configValues, connection );
}
catch ( SQLException sqle ) {
LOG.unableToObtainConnectionMetadata( sqle.getMessage() );
}
finally {
if ( connection != null ) {
jdbcConnectionAccess.releaseConnection( connection );
}
}
}
catch ( SQLException sqle ) {
LOG.unableToObtainConnectionToQueryMetadata( sqle.getMessage() );
dialect = dialectFactory.buildDialect( configValues, null );
}
catch ( UnsupportedOperationException uoe ) {
// user supplied JDBC connections
dialect = dialectFactory.buildDialect( configValues, null );
}
}
else {
dialect = dialectFactory.buildDialect( configValues, null );
}
this.connectionProvider = serviceRegistry.getService( ConnectionProvider.class );
final boolean showSQL = ConfigurationHelper.getBoolean( Environment.SHOW_SQL, configValues, false );
final boolean formatSQL = ConfigurationHelper.getBoolean( Environment.FORMAT_SQL, configValues, false );
this.dialect = dialect;
this.lobCreatorBuilder = (
lobCreatorBuilder == null ?
new LobCreatorBuilder( configValues, null ) :
lobCreatorBuilder
);
this.sqlStatementLogger = new SqlStatementLogger( showSQL, formatSQL );
this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl(
metaSupportsRefCursors,
metaSupportsNamedParams,
metaSupportsScrollable,
metaSupportsGetGeneratedKeys,
metaSupportsBatchUpdates,
metaReportsDDLInTxnSupported,
metaReportsDDLCausesTxnCommit,
parseKeywords( extraKeywordsString ),
parseSQLStateType( sqlStateType ),
lobLocatorUpdateCopy,
schemaName,
catalogName,
typeInfoSet
);
SQLExceptionConverter sqlExceptionConverter = dialect.buildSQLExceptionConverter();
if ( sqlExceptionConverter == null ) {
final StandardSQLExceptionConverter converter = new StandardSQLExceptionConverter();
sqlExceptionConverter = converter;
converter.addDelegate( dialect.buildSQLExceptionConversionDelegate() );
converter.addDelegate( new SQLExceptionTypeDelegate( dialect ) );
// todo : vary this based on extractedMetaDataSupport.getSqlStateType()
converter.addDelegate( new SQLStateConversionDelegate( dialect ) );
}
this.sqlExceptionHelper = new SqlExceptionHelper( sqlExceptionConverter );
}
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 {
connectionProvider.closeConnection( connection );
}
}
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 {
connectionProvider.releaseAnyConnection( connection );
}
}
// todo : add to Environment
public static final String SCHEMA_NAME_RESOLVER = "hibernate.schema_name_resolver";
private SchemaNameResolver determineExplicitSchemaNameResolver(Map configValues) {
Object setting = configValues.get( SCHEMA_NAME_RESOLVER );
if ( SchemaNameResolver.class.isInstance( setting ) ) {
return (SchemaNameResolver) setting;
}
String resolverClassName = (String) setting;
if ( resolverClassName != null ) {
try {
Class resolverClass = ReflectHelper.classForName( resolverClassName, getClass() );
return (SchemaNameResolver) ReflectHelper.getDefaultConstructor( resolverClass ).newInstance();
}
catch ( ClassNotFoundException e ) {
LOG.unableToLocateConfiguredSchemaNameResolver( resolverClassName, e.toString() );
}
catch ( InvocationTargetException e ) {
LOG.unableToInstantiateConfiguredSchemaNameResolver( resolverClassName, e.getTargetException().toString() );
}
catch ( Exception e ) {
LOG.unableToInstantiateConfiguredSchemaNameResolver( resolverClassName, e.toString() );
}
}
return null;
}
private Set<String> parseKeywords(String extraKeywordsString) {
Set<String> keywordSet = new HashSet<String>();
keywordSet.addAll( Arrays.asList( extraKeywordsString.split( "," ) ) );
return keywordSet;
}
private ExtractedDatabaseMetaData.SQLStateType parseSQLStateType(int sqlStateType) {
switch ( sqlStateType ) {
case DatabaseMetaData.sqlStateSQL99 : {
return ExtractedDatabaseMetaData.SQLStateType.SQL99;
}
case DatabaseMetaData.sqlStateXOpen : {
return ExtractedDatabaseMetaData.SQLStateType.XOpen;
}
default : {
return ExtractedDatabaseMetaData.SQLStateType.UNKOWN;
}
}
}
private static class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData {
private final boolean supportsRefCursors;
private final boolean supportsNamedParameters;
private final boolean supportsScrollableResults;
private final boolean supportsGetGeneratedKeys;
private final boolean supportsBatchUpdates;
private final boolean supportsDataDefinitionInTransaction;
private final boolean doesDataDefinitionCauseTransactionCommit;
private final Set<String> extraKeywords;
private final SQLStateType sqlStateType;
private final boolean lobLocatorUpdateCopy;
private final String connectionSchemaName;
private final String connectionCatalogName;
private final LinkedHashSet<TypeInfo> typeInfoSet;
private ExtractedDatabaseMetaDataImpl(
boolean supportsRefCursors,
boolean supportsNamedParameters,
boolean supportsScrollableResults,
boolean supportsGetGeneratedKeys,
boolean supportsBatchUpdates,
boolean supportsDataDefinitionInTransaction,
boolean doesDataDefinitionCauseTransactionCommit,
Set<String> extraKeywords,
SQLStateType sqlStateType,
boolean lobLocatorUpdateCopy,
String connectionSchemaName,
String connectionCatalogName,
LinkedHashSet<TypeInfo> typeInfoSet) {
this.supportsRefCursors = supportsRefCursors;
this.supportsNamedParameters = supportsNamedParameters;
this.supportsScrollableResults = supportsScrollableResults;
this.supportsGetGeneratedKeys = supportsGetGeneratedKeys;
this.supportsBatchUpdates = supportsBatchUpdates;
this.supportsDataDefinitionInTransaction = supportsDataDefinitionInTransaction;
this.doesDataDefinitionCauseTransactionCommit = doesDataDefinitionCauseTransactionCommit;
this.extraKeywords = extraKeywords;
this.sqlStateType = sqlStateType;
this.lobLocatorUpdateCopy = lobLocatorUpdateCopy;
this.connectionSchemaName = connectionSchemaName;
this.connectionCatalogName = connectionCatalogName;
this.typeInfoSet = typeInfoSet;
}
@Override
public boolean supportsRefCursors() {
return supportsRefCursors;
}
@Override
public boolean supportsNamedParameters() {
return supportsNamedParameters;
}
@Override
public boolean supportsScrollableResults() {
return supportsScrollableResults;
}
@Override
public boolean supportsGetGeneratedKeys() {
return supportsGetGeneratedKeys;
}
@Override
public boolean supportsBatchUpdates() {
return supportsBatchUpdates;
}
@Override
public boolean supportsDataDefinitionInTransaction() {
return supportsDataDefinitionInTransaction;
}
@Override
public boolean doesDataDefinitionCauseTransactionCommit() {
return doesDataDefinitionCauseTransactionCommit;
}
@Override
public Set<String> getExtraKeywords() {
return extraKeywords;
}
@Override
public SQLStateType getSqlStateType() {
return sqlStateType;
}
@Override
public boolean doesLobLocatorUpdateCopy() {
return lobLocatorUpdateCopy;
}
@Override
public String getConnectionSchemaName() {
return connectionSchemaName;
}
@Override
public String getConnectionCatalogName() {
return connectionCatalogName;
}
@Override
public LinkedHashSet<TypeInfo> getTypeInfoSet() {
return typeInfoSet;
}
@Override
public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode) {
for ( TypeInfo typeInfo : typeInfoSet ) {
if ( typeInfo.getJdbcTypeCode() == jdbcTypeCode ) {
return typeInfo;
}
}
return null;
}
}
@Override
@ -455,22 +81,22 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi
@Override
public SqlExceptionHelper getSqlExceptionHelper() {
return sqlExceptionHelper;
return jdbcEnvironment.getSqlExceptionHelper();
}
@Override
public Dialect getDialect() {
return dialect;
return jdbcEnvironment.getDialect();
}
@Override
public ExtractedDatabaseMetaData getExtractedMetaDataSupport() {
return extractedMetaDataSupport;
return jdbcEnvironment.getExtractedDatabaseMetaData();
}
@Override
public LobCreator getLobCreator(LobCreationContext lobCreationContext) {
return lobCreatorBuilder.buildLobCreator( lobCreationContext );
return jdbcEnvironment.getLobCreatorBuilder().buildLobCreator( lobCreationContext );
}
@Override
@ -480,6 +106,6 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi
@Override
public JdbcEnvironment getJdbcEnvironment() {
return null; //To change body of implemented methods use File | Settings | File Templates.
return jdbcEnvironment;
}
}

View File

@ -39,7 +39,7 @@ import org.hibernate.HibernateException;
import org.hibernate.JDBCException;
import org.hibernate.engine.jdbc.internal.proxy.ProxyBuilder;
import org.hibernate.engine.jdbc.spi.ConnectionObserver;
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
import org.hibernate.service.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.JdbcResourceRegistry;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;

View File

@ -29,7 +29,8 @@ import java.sql.ResultSet;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.Service;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
@ -44,6 +45,7 @@ public interface JdbcServices extends Service {
*
* @return The connection provider.
*/
@Deprecated
public ConnectionProvider getConnectionProvider();
/**

View File

@ -39,7 +39,7 @@ import org.hibernate.ScrollableResults;
import org.hibernate.cache.spi.CacheKey;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
import org.hibernate.service.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.internal.CriteriaImpl;

View File

@ -26,7 +26,7 @@ package org.hibernate.engine.transaction.spi;
import java.io.Serializable;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
import org.hibernate.service.jdbc.connections.spi.JdbcConnectionAccess;
/**
* Access to services needed in the context of processing transaction requests.

View File

@ -39,7 +39,7 @@ import org.hibernate.SharedSessionContract;
import org.hibernate.StoredProcedureCall;
import org.hibernate.cache.spi.CacheKey;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
import org.hibernate.service.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.query.spi.HQLQueryPlan;
import org.hibernate.engine.query.spi.NativeSQLQueryPlan;
import org.hibernate.engine.query.spi.ParameterMetadata;
@ -333,6 +333,11 @@ public abstract class AbstractSessionImpl implements Serializable, SharedSession
public void releaseConnection(Connection connection) throws SQLException {
connectionProvider.closeConnection( connection );
}
@Override
public boolean supportsAggressiveRelease() {
return connectionProvider.supportsAggressiveRelease();
}
}
private class ContextualJdbcConnectionAccess implements JdbcConnectionAccess, Serializable {
@ -357,5 +362,10 @@ public abstract class AbstractSessionImpl implements Serializable, SharedSession
}
connectionProvider.releaseConnection( tenantIdentifier, connection );
}
@Override
public boolean supportsAggressiveRelease() {
return connectionProvider.supportsAggressiveRelease();
}
}
}

View File

@ -47,7 +47,7 @@ import org.hibernate.StoredProcedureCall;
import org.hibernate.StoredProcedureOutputs;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.engine.ResultSetMappingDefinition;
import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData;
import org.hibernate.service.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn;
import org.hibernate.engine.spi.QueryParameters;

View File

@ -34,7 +34,7 @@ import java.util.Set;
import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.metamodel.Metadata;

View File

@ -47,7 +47,7 @@ public class ObjectName {
/**
* Tries to create an {@code ObjectName} from a name. This form explicitly looks for the form
* {@code catalog.schema.name}. If you need db specific parsing use
* {@link org.hibernate.engine.jdbc.env.spi.SchemaCatalogSupport#parseName} instead
* {@link org.hibernate.service.jdbc.env.spi.QualifiedObjectNameSupport#parseName} instead
*
* @param text simple or qualified name of the database object.
*/

View File

@ -41,9 +41,11 @@ import org.hibernate.service.jdbc.connections.internal.MultiTenantConnectionProv
import org.hibernate.service.jdbc.cursor.internal.RefCursorSupportInitiator;
import org.hibernate.service.jdbc.dialect.internal.DialectFactoryInitiator;
import org.hibernate.service.jdbc.dialect.internal.DialectResolverInitiator;
import org.hibernate.service.jdbc.env.internal.JdbcEnvironmentInitiator;
import org.hibernate.service.jmx.internal.JmxServiceInitiator;
import org.hibernate.service.jndi.internal.JndiServiceInitiator;
import org.hibernate.service.jta.platform.internal.JtaPlatformInitiator;
import org.hibernate.service.schema.internal.SchemaManagementToolInitiator;
import org.hibernate.service.spi.BasicServiceInitiator;
import org.hibernate.tool.hbm2ddl.ImportSqlCommandExtractorInitiator;
@ -72,9 +74,12 @@ public class StandardServiceInitiators {
serviceInitiators.add( DialectResolverInitiator.INSTANCE );
serviceInitiators.add( DialectFactoryInitiator.INSTANCE );
serviceInitiators.add( BatchBuilderInitiator.INSTANCE );
serviceInitiators.add( JdbcEnvironmentInitiator.INSTANCE );
serviceInitiators.add( JdbcServicesInitiator.INSTANCE );
serviceInitiators.add( RefCursorSupportInitiator.INSTANCE );
serviceInitiators.add( SchemaManagementToolInitiator.INSTANCE );
serviceInitiators.add( MutableIdentifierGeneratorFactoryInitiator.INSTANCE);
serviceInitiators.add( JtaPlatformInitiator.INSTANCE );

View File

@ -21,15 +21,15 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.service.schema.spi;
package org.hibernate.service.jdbc.connections.internal;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import org.hibernate.HibernateException;
/**
* Because JDBC (at least up to an including Java 7, JDBC 4) still does not have a notion of
* @author Steve Ebersole
*/
public interface ExistingSequenceMetadataExtractor {
public Iterable<ExistingSequenceMetadata> extractMetadata(DatabaseMetaData databaseMetaData) throws SQLException;
public class UserSuppliedConnectionException extends HibernateException {
public UserSuppliedConnectionException() {
super( "The application must supply JDBC connections" );
}
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.service.jdbc.connections.internal;
import java.sql.Connection;
import java.sql.SQLException;
@ -55,23 +56,17 @@ public class UserSuppliedConnectionProviderImpl implements ConnectionProvider {
}
}
/**
* {@inheritDoc}
*/
@Override
public Connection getConnection() throws SQLException {
throw new UnsupportedOperationException( "The application must supply JDBC connections" );
throw new UserSuppliedConnectionException();
}
/**
* {@inheritDoc}
*/
@Override
public void closeConnection(Connection conn) throws SQLException {
throw new UnsupportedOperationException( "The application must supply JDBC connections" );
throw new UserSuppliedConnectionException();
}
/**
* {@inheritDoc}
*/
@Override
public boolean supportsAggressiveRelease() {
return false;
}

View File

@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.spi;
package org.hibernate.service.jdbc.connections.spi;
import java.io.Serializable;
import java.sql.Connection;
@ -34,6 +34,30 @@ import java.sql.SQLException;
* @author Steve Ebersole
*/
public interface JdbcConnectionAccess extends Serializable {
/**
* Obtain a JDBC connection
*
* @return The obtained connection
*
* @throws SQLException Indicates a problem getting the connection
*/
public Connection obtainConnection() throws SQLException;
/**
* Release a previously obtained connection
*
* @param connection The connection to release
*
* @throws SQLException Indicates a problem releasing the connection
*/
public void releaseConnection(Connection connection) throws SQLException;
/**
* Does the underlying provider of connections support aggressive releasing of connections (and re-acquisition
* of those connections later, if need be) in JTA environments?
*
* @see ConnectionProvider#supportsAggressiveRelease()
* @see MultiTenantConnectionProvider#supportsAggressiveRelease()
*/
public boolean supportsAggressiveRelease();
}

View File

@ -0,0 +1,142 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.env.internal;
import org.hibernate.service.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.jdbc.env.spi.SQLStateType;
/**
* Standard implementation of ExtractedDatabaseMetaData
*
* @author Steve Ebersole
*/
public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData {
private final JdbcEnvironment jdbcEnvironment;
private final boolean supportsRefCursors;
private final boolean supportsNamedParameters;
private final boolean supportsScrollableResults;
private final boolean supportsGetGeneratedKeys;
private final boolean supportsBatchUpdates;
private final boolean supportsDataDefinitionInTransaction;
private final boolean doesDataDefinitionCauseTransactionCommit;
private final SQLStateType sqlStateType;
private final boolean lobLocatorUpdateCopy;
/**
* Form used when {@link java.sql.DatabaseMetaData} is not available.
*
* @param jdbcEnvironment The JDBC environment containing this metadata.
*/
public ExtractedDatabaseMetaDataImpl(JdbcEnvironment jdbcEnvironment) {
this.jdbcEnvironment = jdbcEnvironment;
// if possible, set values that will allow things to still work....
this.supportsRefCursors = false; // Java 8 feature, safest to say not.
this.supportsNamedParameters = false;
this.supportsScrollableResults = true;
this.supportsGetGeneratedKeys = false;
this.supportsBatchUpdates = true;
this.sqlStateType = SQLStateType.UNKNOWN;
this.lobLocatorUpdateCopy = true;
// ugh my favorites...
this.supportsDataDefinitionInTransaction = false;
this.doesDataDefinitionCauseTransactionCommit = false;
}
public ExtractedDatabaseMetaDataImpl(
JdbcEnvironmentImpl jdbcEnvironment,
boolean supportsRefCursors,
boolean supportsNamedParameters,
boolean supportsScrollableResults,
boolean supportsGetGeneratedKeys,
boolean supportsBatchUpdates,
boolean supportsDataDefinitionInTransaction,
boolean doesDataDefinitionCauseTransactionCommit,
SQLStateType sqlStateType,
boolean lobLocatorUpdateCopy) {
this.jdbcEnvironment = jdbcEnvironment;
this.supportsRefCursors = supportsRefCursors;
this.supportsNamedParameters = supportsNamedParameters;
this.supportsScrollableResults = supportsScrollableResults;
this.supportsGetGeneratedKeys = supportsGetGeneratedKeys;
this.supportsBatchUpdates = supportsBatchUpdates;
this.supportsDataDefinitionInTransaction = supportsDataDefinitionInTransaction;
this.doesDataDefinitionCauseTransactionCommit = doesDataDefinitionCauseTransactionCommit;
this.sqlStateType = sqlStateType;
this.lobLocatorUpdateCopy = lobLocatorUpdateCopy;
}
@Override
public JdbcEnvironment getJdbcEnvironment() {
return jdbcEnvironment;
}
@Override
public boolean supportsRefCursors() {
return supportsRefCursors;
}
@Override
public boolean supportsNamedParameters() {
return supportsNamedParameters;
}
@Override
public boolean supportsScrollableResults() {
return supportsScrollableResults;
}
@Override
public boolean supportsGetGeneratedKeys() {
return supportsGetGeneratedKeys;
}
@Override
public boolean supportsBatchUpdates() {
return supportsBatchUpdates;
}
@Override
public boolean supportsDataDefinitionInTransaction() {
return supportsDataDefinitionInTransaction;
}
@Override
public boolean doesDataDefinitionCauseTransactionCommit() {
return doesDataDefinitionCauseTransactionCommit;
}
@Override
public SQLStateType getSqlStateType() {
return sqlStateType;
}
@Override
public boolean doesLobLocatorUpdateCopy() {
return lobLocatorUpdateCopy;
}
}

View File

@ -0,0 +1,117 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.env.internal;
import java.util.Set;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.internal.TypeInfo;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.service.Service;
import org.hibernate.service.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.service.jdbc.env.spi.IdentifierHelper;
import org.hibernate.service.jdbc.env.spi.QualifiedObjectNameSupport;
/**
* Initial look at this concept we keep talking about with merging information from {@link java.sql.DatabaseMetaData}
* and {@link org.hibernate.dialect.Dialect}
*
* @author Steve Ebersole
*/
public interface JdbcEnvironment extends Service {
/**
* Get the dialect for this environment.
*
* @return The dialect.
*/
public Dialect getDialect();
/**
* Access to the bits of information we pulled off the JDBC {@link java.sql.DatabaseMetaData} (that did not get
* "interpreted" into the helpers/delegates available here).
*
* @return The values extracted from JDBC DatabaseMetaData
*/
public ExtractedDatabaseMetaData getExtractedDatabaseMetaData();
/**
* Get the current database catalog. Typically will come from either {@link java.sql.Connection#getCatalog()}
* or {@link org.hibernate.cfg.AvailableSettings#DEFAULT_CATALOG}.
*
* @return The current catalog.
*/
public Identifier getCurrentCatalog();
/**
* Get the current database catalog. Typically will come from either
* {@link org.hibernate.service.jdbc.env.spi.SchemaNameResolver#resolveSchemaName(java.sql.Connection)} or
* {@link org.hibernate.cfg.AvailableSettings#DEFAULT_CATALOG}.
*
* @return The current schema
*/
public Identifier getCurrentSchema();
/**
* Obtain support for reading and writing qualified object names.
*
* @return Qualified name support.
*/
public QualifiedObjectNameSupport getQualifiedObjectNameSupport();
/**
* Obtain the helper for dealing with identifiers in this environment.
*
* @return The identifier helper.
*/
public IdentifierHelper getIdentifierHelper();
/**
* Get the complete set of reserved words for this environment. These are significant because they represent
* the complete set of terms that MUST BE quoted if used as identifiers. This allows us to apply auto-quoting
* in the metamodel based on these terms.
*
* Note that the standard IdentifierHelper returned by {@link #getIdentifierHelper()} already accounts for
* auto-quoting :) yaay!
*
* @return Reserved words
*/
public Set<String> getReservedWords();
/**
* Obtain the helper for dealing with JDBC {@link java.sql.SQLException} faults.
*
* @return This environment's helper.
*/
public SqlExceptionHelper getSqlExceptionHelper();
/**
* Find type information for the type identified by the given "JDBC type code".
*
* @param jdbcTypeCode The JDBC type code.
*
* @return The corresponding type info.
*/
public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode);
}

View File

@ -0,0 +1,294 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.env.internal;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.internal.TypeInfo;
import org.hibernate.engine.jdbc.internal.TypeInfoExtracter;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.exception.internal.SQLExceptionTypeDelegate;
import org.hibernate.exception.internal.SQLStateConversionDelegate;
import org.hibernate.exception.internal.StandardSQLExceptionConverter;
import org.hibernate.exception.spi.SQLExceptionConverter;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.service.classloading.spi.ClassLoaderService;
import org.hibernate.service.config.spi.ConfigurationService;
import org.hibernate.service.config.spi.StandardConverters;
import org.hibernate.service.jdbc.cursor.internal.StandardRefCursorSupport;
import org.hibernate.service.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.service.jdbc.env.spi.IdentifierHelper;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.jdbc.env.spi.LobCreatorBuilder;
import org.hibernate.service.jdbc.env.spi.QualifiedObjectNameSupport;
import org.hibernate.service.jdbc.env.spi.SQLStateType;
import org.hibernate.service.jdbc.env.spi.SchemaNameResolver;
import org.hibernate.service.jdbc.env.spi.StandardQualifiedObjectNameSupportImpl;
import org.hibernate.service.spi.ServiceRegistryImplementor;
/**
* @author Steve Ebersole
*/
public class JdbcEnvironmentImpl implements JdbcEnvironment {
private final ServiceRegistryImplementor serviceRegistry;
private final Dialect dialect;
private final SqlExceptionHelper sqlExceptionHelper;
private final ExtractedDatabaseMetaData extractedMetaDataSupport;
private final Set<String> reservedWords;
private final Identifier currentCatalog;
private final Identifier currentSchema;
private final IdentifierHelper identifierHelper;
private final QualifiedObjectNameSupport qualifiedObjectNameSupport;
private final LobCreatorBuilderImpl lobCreatorBuilder;
private final LinkedHashSet<TypeInfo> typeInfoSet = new LinkedHashSet<TypeInfo>();
/**
* Constructor form used when the JDBC {@link DatabaseMetaData} is not available.
*
* @param serviceRegistry The service registry
* @param dialect The resolved dialect.
*/
public JdbcEnvironmentImpl(ServiceRegistryImplementor serviceRegistry, Dialect dialect) {
this.serviceRegistry = serviceRegistry;
this.dialect = dialect;
this.sqlExceptionHelper = buildSqlExceptionHelper( dialect );
this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl( this );
// make sure reserved-words, current-catalog and current-schema happen before the identifier-helper!
this.reservedWords = dialect.getKeywords();
this.currentCatalog = Identifier.toIdentifier(
serviceRegistry.getService( ConfigurationService.class )
.getSetting( AvailableSettings.DEFAULT_CATALOG, StandardConverters.STRING )
);
this.currentSchema = Identifier.toIdentifier(
serviceRegistry.getService( ConfigurationService.class )
.getSetting( AvailableSettings.DEFAULT_SCHEMA, StandardConverters.STRING )
);
// a simple temporary impl that works on H2
this.identifierHelper = new NormalizingIdentifierHelperImpl(
this,
true, // storesMixedCaseQuotedIdentifiers
false, // storesLowerCaseQuotedIdentifiers
false, // storesUpperCaseQuotedIdentifiers
true, // storesUpperCaseIdentifiers
false // storesLowerCaseIdentifiers
);
// again, a simple temporary impl that works on H2
this.qualifiedObjectNameSupport = new StandardQualifiedObjectNameSupportImpl(
".",
true,
dialect.openQuote(),
dialect.closeQuote()
);
this.lobCreatorBuilder = LobCreatorBuilderImpl.makeLobCreatorBuilder();
}
public JdbcEnvironmentImpl(ServiceRegistryImplementor serviceRegistry, Dialect dialect, DatabaseMetaData dbmd) throws SQLException {
this.serviceRegistry = serviceRegistry;
this.dialect = dialect;
this.sqlExceptionHelper = buildSqlExceptionHelper( dialect );
this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl(
this,
StandardRefCursorSupport.supportsRefCursors( dbmd ),
dbmd.supportsNamedParameters(),
dbmd.supportsResultSetType( ResultSet.TYPE_SCROLL_INSENSITIVE ),
dbmd.supportsGetGeneratedKeys(),
dbmd.supportsBatchUpdates(),
!dbmd.dataDefinitionIgnoredInTransactions(),
dbmd.dataDefinitionCausesTransactionCommit(),
parseSQLStateType( dbmd.getSQLStateType() ),
dbmd.locatorsUpdateCopy()
);
// make sure reserved-words happen before the identifier-helper!
this.reservedWords = buildMergedReservedWords( dialect, dbmd );
this.identifierHelper = new NormalizingIdentifierHelperImpl(
this,
dbmd.storesMixedCaseQuotedIdentifiers(),
dbmd.storesLowerCaseQuotedIdentifiers(),
dbmd.storesUpperCaseQuotedIdentifiers(),
dbmd.storesUpperCaseIdentifiers(),
dbmd.storesLowerCaseIdentifiers()
);
// and that current-catalog and current-schema happen after it
this.currentCatalog = determineCurrentCatalog( dbmd );
this.currentSchema = determineCurrentSchema( dbmd );
this.qualifiedObjectNameSupport = new StandardQualifiedObjectNameSupportImpl(
dbmd.getCatalogSeparator(),
dbmd.isCatalogAtStart(),
dialect.openQuote(),
dialect.closeQuote()
);
this.typeInfoSet.addAll( TypeInfoExtracter.extractTypeInfo( dbmd ) );
this.lobCreatorBuilder = LobCreatorBuilderImpl.makeLobCreatorBuilder(
serviceRegistry.getService( ConfigurationService.class ).getSettings(),
dbmd.getConnection()
);
}
private SQLStateType parseSQLStateType(int sqlStateType) {
switch ( sqlStateType ) {
case DatabaseMetaData.sqlStateSQL99 : {
return SQLStateType.SQL99;
}
case DatabaseMetaData.sqlStateXOpen : {
return SQLStateType.XOpen;
}
default : {
return SQLStateType.UNKNOWN;
}
}
}
@SuppressWarnings("deprecation")
private SqlExceptionHelper buildSqlExceptionHelper(Dialect dialect) {
SQLExceptionConverter sqlExceptionConverter = dialect.buildSQLExceptionConverter();
if ( sqlExceptionConverter == null ) {
final StandardSQLExceptionConverter converter = new StandardSQLExceptionConverter();
sqlExceptionConverter = converter;
converter.addDelegate( dialect.buildSQLExceptionConversionDelegate() );
converter.addDelegate( new SQLExceptionTypeDelegate( dialect ) );
converter.addDelegate( new SQLStateConversionDelegate( dialect ) );
}
return new SqlExceptionHelper( sqlExceptionConverter );
}
private Identifier determineCurrentCatalog(DatabaseMetaData dbmd) throws SQLException {
String currentCatalogName = dbmd.getConnection().getCatalog();
if ( currentCatalogName != null ) {
// intentionally using fromMetaDataObjectName rather than fromMetaDataCatalogName !!!
return identifierHelper.fromMetaDataObjectName( currentCatalogName );
}
else {
currentCatalogName = serviceRegistry.getService( ConfigurationService.class )
.getSetting( AvailableSettings.DEFAULT_CATALOG, StandardConverters.STRING );
return Identifier.toIdentifier( currentCatalogName );
}
}
private Identifier determineCurrentSchema(DatabaseMetaData dbmd) throws SQLException {
String currentSchemaName = locateSchemaNameResolver().resolveSchemaName( dbmd.getConnection() );
if ( currentSchemaName != null ) {
// intentionally using fromMetaDataObjectName rather than fromMetaDataSchemaName !!!
return identifierHelper.fromMetaDataObjectName( currentSchemaName );
}
else {
currentSchemaName = serviceRegistry.getService( ConfigurationService.class )
.getSetting( AvailableSettings.DEFAULT_SCHEMA, StandardConverters.STRING );
return Identifier.toIdentifier( currentSchemaName );
}
}
private SchemaNameResolver locateSchemaNameResolver() {
final Object setting = serviceRegistry.getService( ConfigurationService.class )
.getSettings()
.get( AvailableSettings.SCHEMA_NAME_RESOLVER );
return serviceRegistry.getService( ClassLoaderService.class )
.getStrategyInstanceResolver()
.resolveDefaultableStrategyInstance( setting, SchemaNameResolver.class, TemporarySchemaNameResolver.INSTANCE );
}
private Set<String> buildMergedReservedWords(Dialect dialect, DatabaseMetaData dbmd) throws SQLException {
Set<String> reservedWords = new HashSet<String>();
reservedWords.addAll( dialect.getKeywords() );
// todo : do we need to explicitly handle SQL:2003 keywords?
reservedWords.addAll( Arrays.asList( dbmd.getSQLKeywords().split( "," ) ) );
return reservedWords;
}
@Override
public Dialect getDialect() {
return dialect;
}
@Override
public ExtractedDatabaseMetaData getExtractedDatabaseMetaData() {
return extractedMetaDataSupport;
}
@Override
public Identifier getCurrentCatalog() {
return currentCatalog;
}
@Override
public Identifier getCurrentSchema() {
return currentSchema;
}
@Override
public QualifiedObjectNameSupport getQualifiedObjectNameSupport() {
return qualifiedObjectNameSupport;
}
@Override
public IdentifierHelper getIdentifierHelper() {
return identifierHelper;
}
@Override
public Set<String> getReservedWords() {
return reservedWords;
}
@Override
public SqlExceptionHelper getSqlExceptionHelper() {
return sqlExceptionHelper;
}
@Override
public LobCreatorBuilder getLobCreatorBuilder() {
return lobCreatorBuilder;
}
@Override
public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode) {
for ( TypeInfo typeInfo : typeInfoSet ) {
if ( typeInfo.getJdbcTypeCode() == jdbcTypeCode ) {
return typeInfo;
}
}
return null;
}
}

View File

@ -0,0 +1,186 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.env.internal;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.Map;
import org.jboss.logging.Logger;
import org.hibernate.MultiTenancyStrategy;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.jdbc.connections.internal.UserSuppliedConnectionException;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.service.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.service.jdbc.connections.spi.MultiTenantConnectionProvider;
import org.hibernate.service.jdbc.dialect.spi.DialectFactory;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.spi.BasicServiceInitiator;
import org.hibernate.service.spi.ServiceRegistryImplementor;
/**
* @author Steve Ebersole
*/
public class JdbcEnvironmentInitiator implements BasicServiceInitiator<JdbcEnvironment> {
private static final CoreMessageLogger log = Logger.getMessageLogger(
CoreMessageLogger.class,
JdbcEnvironmentInitiator.class.getName()
);
public static final JdbcEnvironmentInitiator INSTANCE = new JdbcEnvironmentInitiator();
@Override
public Class<JdbcEnvironment> getServiceInitiated() {
return JdbcEnvironment.class;
}
@Override
public JdbcEnvironment initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
final DialectFactory dialectFactory = registry.getService( DialectFactory.class );
boolean useJdbcMetadata = ConfigurationHelper.getBoolean(
"hibernate.temp.use_jdbc_metadata_defaults",
configurationValues,
true
);
if ( useJdbcMetadata ) {
final JdbcConnectionAccess jdbcConnectionAccess = buildJdbcConnectionAccess( configurationValues, registry );
try {
final Connection connection = jdbcConnectionAccess.obtainConnection();
try {
final DatabaseMetaData dbmd = connection.getMetaData();
if ( log.isDebugEnabled() ) {
log.debugf(
"Database ->\n"
+ " name : %s\n"
+ " version : %s\n"
+ " major : %s\n"
+ " minor : %s",
dbmd.getDatabaseProductName(),
dbmd.getDatabaseProductVersion(),
dbmd.getDatabaseMajorVersion(),
dbmd.getDatabaseMinorVersion()
);
log.debugf(
"Driver ->\n"
+ " name : %s\n"
+ " version : %s\n"
+ " major : %s\n"
+ " minor : %s",
dbmd.getDriverName(),
dbmd.getDriverVersion(),
dbmd.getDriverMajorVersion(),
dbmd.getDriverMinorVersion()
);
log.debugf( "JDBC version : %s.%s", dbmd.getJDBCMajorVersion(), dbmd.getJDBCMinorVersion() );
}
return new JdbcEnvironmentImpl(
registry,
dialectFactory.buildDialect( configurationValues, connection ),
dbmd
);
}
catch (SQLException e) {
log.unableToObtainConnectionMetadata( e.getMessage() );
}
finally {
try {
jdbcConnectionAccess.releaseConnection( connection );
}
catch (SQLException ignore) {
}
}
}
catch (Exception e) {
log.unableToObtainConnectionToQueryMetadata( e.getMessage() );
}
}
// if we get here, either we were asked to not use JDBC metadata or accessing the JDBC metadata failed.
return new JdbcEnvironmentImpl( registry, dialectFactory.buildDialect( configurationValues, null ) );
}
private JdbcConnectionAccess buildJdbcConnectionAccess(Map configValues, ServiceRegistryImplementor registry) {
final MultiTenancyStrategy multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configValues );
if ( MultiTenancyStrategy.NONE == multiTenancyStrategy ) {
ConnectionProvider connectionProvider = registry.getService( ConnectionProvider.class );
return new ConnectionProviderJdbcConnectionAccess( connectionProvider );
}
else {
final MultiTenantConnectionProvider multiTenantConnectionProvider = registry.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 {
connectionProvider.closeConnection( connection );
}
@Override
public boolean supportsAggressiveRelease() {
return connectionProvider.supportsAggressiveRelease();
}
}
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 {
connectionProvider.releaseAnyConnection( connection );
}
@Override
public boolean supportsAggressiveRelease() {
return connectionProvider.supportsAggressiveRelease();
}
}
}

View File

@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.internal;
package org.hibernate.service.jdbc.env.internal;
import java.lang.reflect.Method;
import java.sql.Connection;
@ -38,49 +38,70 @@ import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.jdbc.NonContextualLobCreator;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.jdbc.env.spi.LobCreatorBuilder;
/**
* Builds {@link LobCreator} instances based on the capabilities of the environment.
*
* @author Steve Ebersole
*/
public class LobCreatorBuilder {
public class LobCreatorBuilderImpl implements LobCreatorBuilder {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, LobCreatorBuilderImpl.class.getName());
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, LobCreatorBuilder.class.getName());
private final boolean useContextualLobCreation;
private boolean useContextualLobCreation;
private LobCreatorBuilderImpl(boolean useContextualLobCreation) {
this.useContextualLobCreation = useContextualLobCreation;
}
@Override
public LobCreator buildLobCreator(LobCreationContext lobCreationContext) {
return useContextualLobCreation
? new ContextualLobCreator( lobCreationContext )
: NonContextualLobCreator.INSTANCE;
}
// factory methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* The public factory method for obtaining the appropriate (according to given JDBC {@link java.sql.Connection}.
*
* The public factory method for obtaining the appropriate LOB creator (according to given
* JDBC {@link java.sql.Connection}).
*
* @param jdbcConnection A JDBC {@link java.sql.Connection} which can be used to gauge the drivers level of support,
* specifically for creating LOB references.
*/
public LobCreatorBuilder(Map configValues, Connection jdbcConnection) {
this.useContextualLobCreation = useContextualLobCreation( configValues, jdbcConnection );
public static LobCreatorBuilderImpl makeLobCreatorBuilder(Map configValues, Connection jdbcConnection) {
return new LobCreatorBuilderImpl( useContextualLobCreation( configValues, jdbcConnection ) );
}
/**
* For used when JDBC Connection is not available.
*
* @return Appropriate LobCreatorBuilder
*/
public static LobCreatorBuilderImpl makeLobCreatorBuilder() {
LOG.disablingContextualLOBCreationSinceConnectionNull();
return new LobCreatorBuilderImpl( false );
}
private static final Class[] NO_ARG_SIG = new Class[0];
private static final Object[] NO_ARGS = new Object[0];
/**
* Basically here we are simply checking whether we can call the {@link Connection} methods for
* LOB creation added in JDBC 4. We not only check whether the {@link Connection} declares these methods,
* but also whether the actual {@link Connection} instance implements them (i.e. can be called without simply
* throwing an exception).
*
* @param jdbcConnection The connection which can be used in level-of-support testing.
*
* @return True if the connection can be used to create LOBs; false otherwise.
*/
private static boolean useContextualLobCreation(Map configValues, Connection jdbcConnection) {
// Basically here we are simply checking whether we can call the {@link Connection} methods for
// LOB creation added in JDBC 4. We not only check whether the {@link Connection} declares these methods,
// but also whether the actual {@link Connection} instance implements them (i.e. can be called without simply
// throwing an exception).
// First, did the user explicitly configure to use non-contextual creation?
boolean isNonContextualLobCreationRequired =
ConfigurationHelper.getBoolean( Environment.NON_CONTEXTUAL_LOB_CREATION, configValues );
if ( isNonContextualLobCreationRequired ) {
LOG.disablingContextualLOBCreation( Environment.NON_CONTEXTUAL_LOB_CREATION );
return false;
}
if ( jdbcConnection == null ) {
LOG.disablingContextualLOBCreationSinceConnectionNull();
return false;
@ -126,10 +147,4 @@ public class LobCreatorBuilder {
return false;
}
public LobCreator buildLobCreator(LobCreationContext lobCreationContext) {
return useContextualLobCreation
? new ContextualLobCreator( lobCreationContext )
: NonContextualLobCreator.INSTANCE;
}
}

View File

@ -21,12 +21,12 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.env.internal;
package org.hibernate.service.jdbc.env.internal;
import org.jboss.logging.Logger;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.jdbc.env.spi.IdentifierHelper;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.spi.relational.Identifier;

View File

@ -21,14 +21,14 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.env.internal;
package org.hibernate.service.jdbc.env.internal;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver;
import org.hibernate.service.jdbc.env.spi.SchemaNameResolver;
/**
* Temporary implementation that works for H2.

View File

@ -0,0 +1 @@
package org.hibernate.service.jdbc.env;

View File

@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.spi;
package org.hibernate.service.jdbc.env.spi;
import java.util.LinkedHashSet;
import java.util.Set;
@ -37,12 +37,12 @@ import org.hibernate.engine.jdbc.internal.TypeInfo;
*/
@SuppressWarnings( {"UnusedDeclaration"})
public interface ExtractedDatabaseMetaData {
public enum SQLStateType {
XOpen,
SQL99,
UNKOWN
}
/**
* Obtain the JDBC Environment from which this metadata came.
*
* @return The JDBC environment
*/
public JdbcEnvironment getJdbcEnvironment();
/**
* Does the driver report supporting named parameters?
@ -107,15 +107,6 @@ public interface ExtractedDatabaseMetaData {
*/
public boolean doesDataDefinitionCauseTransactionCommit();
/**
* Get the list of extra keywords (beyond standard SQL92 keywords) reported by the driver.
*
* @return The extra keywords used by this database.
*
* @see java.sql.DatabaseMetaData#getSQLKeywords()
*/
public Set<String> getExtraKeywords();
/**
* Retrieve the type of codes the driver says it uses for {@code SQLState}. They might follow either
* the X/Open standard or the SQL92 standard.
@ -134,36 +125,4 @@ public interface ExtractedDatabaseMetaData {
* @see java.sql.DatabaseMetaData#locatorsUpdateCopy()
*/
public boolean doesLobLocatorUpdateCopy();
/**
* Retrieve the name of the schema in effect when we connected to the database.
*
* @return The schema name
*/
public String getConnectionSchemaName();
/**
* Retrieve the name of the catalog in effect when we connected to the database.
*
* @return The catalog name
*/
public String getConnectionCatalogName();
/**
* Set of type info reported by the driver.
*
* @return The type information obtained from the driver.
*
* @see java.sql.DatabaseMetaData#getTypeInfo()
*/
public LinkedHashSet<TypeInfo> getTypeInfoSet();
/**
* Set of type info reported by the driver.
*
* @return The type information obtained from the driver.
*
* @see java.sql.DatabaseMetaData#getTypeInfo()
*/
public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode);
}

View File

@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.env.spi;
package org.hibernate.service.jdbc.env.spi;
import org.hibernate.metamodel.spi.relational.Identifier;

View File

@ -0,0 +1,121 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.env.spi;
import java.util.Set;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.internal.TypeInfo;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.service.Service;
/**
* Initial look at this concept we keep talking about with merging information from {@link java.sql.DatabaseMetaData}
* and {@link org.hibernate.dialect.Dialect}
*
* @author Steve Ebersole
*/
public interface JdbcEnvironment extends Service {
/**
* Get the dialect for this environment.
*
* @return The dialect.
*/
public Dialect getDialect();
/**
* Access to the bits of information we pulled off the JDBC {@link java.sql.DatabaseMetaData} (that did not get
* "interpreted" into the helpers/delegates available here).
*
* @return The values extracted from JDBC DatabaseMetaData
*/
public ExtractedDatabaseMetaData getExtractedDatabaseMetaData();
/**
* Get the current database catalog. Typically will come from either {@link java.sql.Connection#getCatalog()}
* or {@link org.hibernate.cfg.AvailableSettings#DEFAULT_CATALOG}.
*
* @return The current catalog.
*/
public Identifier getCurrentCatalog();
/**
* Get the current database catalog. Typically will come from either
* {@link SchemaNameResolver#resolveSchemaName(java.sql.Connection)} or
* {@link org.hibernate.cfg.AvailableSettings#DEFAULT_CATALOG}.
*
* @return The current schema
*/
public Identifier getCurrentSchema();
/**
* Obtain support for reading and writing qualified object names.
*
* @return Qualified name support.
*/
public QualifiedObjectNameSupport getQualifiedObjectNameSupport();
/**
* Obtain the helper for dealing with identifiers in this environment.
*
* @return The identifier helper.
*/
public IdentifierHelper getIdentifierHelper();
/**
* Get the complete set of reserved words for this environment. These are significant because they represent
* the complete set of terms that MUST BE quoted if used as identifiers. This allows us to apply auto-quoting
* in the metamodel based on these terms.
*
* Note that the standard IdentifierHelper returned by {@link #getIdentifierHelper()} already accounts for
* auto-quoting :) yaay!
*
* @return Reserved words
*/
public Set<String> getReservedWords();
/**
* Obtain the helper for dealing with JDBC {@link java.sql.SQLException} faults.
*
* @return This environment's helper.
*/
public SqlExceptionHelper getSqlExceptionHelper();
/**
* Retrieve the delegate for building {@link org.hibernate.engine.jdbc.LobCreator} instances.
*
* @return The LobCreator builder.
*/
public LobCreatorBuilder getLobCreatorBuilder();
/**
* Find type information for the type identified by the given "JDBC type code".
*
* @param jdbcTypeCode The JDBC type code.
*
* @return The corresponding type info.
*/
public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode);
}

View File

@ -21,35 +21,14 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.service.schema.spi;
package org.hibernate.service.jdbc.env.spi;
import org.hibernate.TruthValue;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.jdbc.LobCreator;
/**
* Information about existing columns
*
* @author Christoph Sturm
* @author Steve Ebersole
*/
public interface ExistingColumnMetadata {
public ExistingTableMetadata getContainingTableMetadata();
public Identifier getColumnIdentifier();
public TruthValue getNullable();
public int getTypeCode();
public String getTypeName();
public int getColumnSize();
public int getDecimalDigits();
public interface LobCreatorBuilder {
LobCreator buildLobCreator(LobCreationContext lobCreationContext);
}

View File

@ -21,16 +21,18 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.env.spi;
package org.hibernate.service.jdbc.env.spi;
import org.hibernate.metamodel.spi.relational.ObjectName;
/**
* Defines the support for dealing with schemas and catalogs
* Defines support for reading and writing qualified object names to and from the database. Generally speaking
* Hibernate itself only uses {@link #formatName}. Most times when it is "parsing" object names it is coming from
* mappings, in which case we expect simple dot-separated syntax and apply {@link ObjectName#parse}
*
* @author Steve Ebersole
*/
public interface SchemaCatalogSupport {
public interface QualifiedObjectNameSupport {
/**
* Performs formatting of an ObjectName to its String representation
*

View File

@ -21,15 +21,15 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.service.schema.spi;
import org.hibernate.metamodel.spi.relational.ObjectName;
package org.hibernate.service.jdbc.env.spi;
/**
* Access to information about existing sequences
* Enum interpretation of the valid values from {@link java.sql.DatabaseMetaData#getSQLStateType()}
*
* @author Steve Ebersole
*/
public interface ExistingSequenceMetadata {
public ObjectName getSequenceName();
public enum SQLStateType {
XOpen,
SQL99,
UNKNOWN
}

View File

@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.env.spi;
package org.hibernate.service.jdbc.env.spi;
import java.sql.Connection;
import java.sql.SQLException;

View File

@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.env.spi;
package org.hibernate.service.jdbc.env.spi;
import java.util.regex.Pattern;
@ -33,7 +33,7 @@ import org.hibernate.metamodel.spi.relational.ObjectName;
/**
* @author Steve Ebersole
*/
public class StandardSchemaCatalogSupportImpl implements SchemaCatalogSupport {
public class StandardQualifiedObjectNameSupportImpl implements QualifiedObjectNameSupport {
public static final char DEFAULT_QUOTE_START = '\'';
public static final char DEFAULT_QUOTE_END = '\'';
public static final String DEFAULT_CATALOG_SEPARATOR = ".";
@ -45,7 +45,7 @@ public class StandardSchemaCatalogSupportImpl implements SchemaCatalogSupport {
private final Pattern splitPattern;
public StandardSchemaCatalogSupportImpl(
public StandardQualifiedObjectNameSupportImpl(
String catalogSeparator,
boolean catalogAfterName,
char quotedStart,
@ -60,19 +60,19 @@ public class StandardSchemaCatalogSupportImpl implements SchemaCatalogSupport {
: Pattern.compile( "[\\." + catalogSeparator + "]" );
}
public StandardSchemaCatalogSupportImpl() {
public StandardQualifiedObjectNameSupportImpl() {
this( DEFAULT_CATALOG_SEPARATOR, false, DEFAULT_QUOTE_START, DEFAULT_QUOTE_END );
}
public StandardSchemaCatalogSupportImpl(String catalogSeparator, boolean catalogAfterName, Dialect dialect) {
public StandardQualifiedObjectNameSupportImpl(String catalogSeparator, boolean catalogAfterName, Dialect dialect) {
this( catalogSeparator, catalogAfterName, dialect.openQuote(), dialect.closeQuote() );
}
public StandardSchemaCatalogSupportImpl(Dialect dialect) {
public StandardQualifiedObjectNameSupportImpl(Dialect dialect) {
this( DEFAULT_CATALOG_SEPARATOR, false, dialect );
}
public StandardSchemaCatalogSupportImpl(String catalogSeparator, boolean catalogAfterName) {
public StandardQualifiedObjectNameSupportImpl(String catalogSeparator, boolean catalogAfterName) {
this( catalogSeparator, catalogAfterName, DEFAULT_QUOTE_START, DEFAULT_QUOTE_END );
}

View File

@ -25,15 +25,17 @@ package org.hibernate.service.schema.internal;
import org.hibernate.TruthValue;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.service.schema.spi.ExistingColumnMetadata;
import org.hibernate.service.schema.spi.ExistingTableMetadata;
import org.hibernate.service.schema.spi.ColumnInformation;
import org.hibernate.service.schema.spi.TableInformation;
/**
* JDBC column metadata
*
* @author Christoph Sturm
* @author Steve Ebersole
*/
public class ExistingColumnMetadataImpl implements ExistingColumnMetadata {
private final ExistingTableMetadata containingTableMetadata;
public class ColumnInformationImpl implements ColumnInformation {
private final TableInformation containingTableInformation;
private final Identifier columnIdentifier;
private final int typeCode;
@ -42,15 +44,15 @@ public class ExistingColumnMetadataImpl implements ExistingColumnMetadata {
private final int decimalDigits;
private final TruthValue nullable;
public ExistingColumnMetadataImpl(
ExistingTableMetadata containingTableMetadata,
public ColumnInformationImpl(
TableInformation containingTableInformation,
Identifier columnIdentifier,
int typeCode,
String typeName,
int columnSize,
int decimalDigits,
TruthValue nullable) {
this.containingTableMetadata = containingTableMetadata;
this.containingTableInformation = containingTableInformation;
this.columnIdentifier = columnIdentifier;
this.typeCode = typeCode;
this.typeName = typeName;
@ -60,8 +62,8 @@ public class ExistingColumnMetadataImpl implements ExistingColumnMetadata {
}
@Override
public ExistingTableMetadata getContainingTableMetadata() {
return containingTableMetadata;
public TableInformation getContainingTableInformation() {
return containingTableInformation;
}
@Override
@ -95,7 +97,7 @@ public class ExistingColumnMetadataImpl implements ExistingColumnMetadata {
}
public String toString() {
return "ExistingColumnMetadata(" + columnIdentifier + ')';
return "ColumnInformation(" + columnIdentifier + ')';
}
}

View File

@ -31,25 +31,25 @@ import java.util.Map;
import java.util.StringTokenizer;
import org.hibernate.TruthValue;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.jdbc.env.spi.IdentifierHelper;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.metamodel.spi.relational.Schema;
import org.hibernate.service.schema.spi.ExistingColumnMetadata;
import org.hibernate.service.schema.spi.ExistingDatabaseMetaData;
import org.hibernate.service.schema.spi.ExistingSequenceMetadata;
import org.hibernate.service.schema.spi.ExistingTableMetadata;
import org.hibernate.service.schema.spi.ColumnInformation;
import org.hibernate.service.schema.spi.DatabaseInformation;
import org.hibernate.service.schema.spi.SequenceInformation;
import org.hibernate.service.schema.spi.TableInformation;
/**
* @author Steve Ebersole
*/
public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData {
public class DatabaseInformationImpl implements DatabaseInformation {
private final JdbcEnvironment jdbcEnvironment;
private final DatabaseMetaData databaseMetaData;
private final Map<ObjectName,ExistingTableMetadataImpl> tables = new HashMap<ObjectName, ExistingTableMetadataImpl>();
private final Map<ObjectName,ExistingSequenceMetadata> sequences;
private final Map<ObjectName,TableInformationImpl> tables = new HashMap<ObjectName, TableInformationImpl>();
private final Map<ObjectName,SequenceInformation> sequences;
public static Builder builder(JdbcEnvironment jdbcEnvironment, DatabaseMetaData databaseMetaData) {
try {
@ -60,7 +60,7 @@ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData {
}
}
private ExistingDatabaseMetaDataImpl(JdbcEnvironment jdbcEnvironment, DatabaseMetaData databaseMetaData) throws SQLException {
private DatabaseInformationImpl(JdbcEnvironment jdbcEnvironment, DatabaseMetaData databaseMetaData) throws SQLException {
this.jdbcEnvironment = jdbcEnvironment;
this.databaseMetaData = databaseMetaData;
this.sequences = loadSequenceMetadataMap();
@ -91,30 +91,31 @@ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData {
);
final ObjectName tableName = new ObjectName( catalogIdentifier, schemaIdentifier, tableIdentifier );
// make sure it does not already exist...
ExistingTableMetadataImpl tableMetadata = tables.get( tableName );
TableInformationImpl tableMetadata = tables.get( tableName );
if ( tableMetadata != null ) {
throw new IllegalStateException( "Table already found on parsing database metadata [" + tableName + "]" );
}
tableMetadata = new ExistingTableMetadataImpl( this, tableName );
tableMetadata = new TableInformationImpl( this, tableName );
tables.put( toMapKey( tableName ), tableMetadata );
}
}
private Map<ObjectName,ExistingSequenceMetadata> loadSequenceMetadataMap() throws SQLException {
Map<ObjectName,ExistingSequenceMetadata> sequences = new HashMap<ObjectName, ExistingSequenceMetadata>();
final Iterable<ExistingSequenceMetadata> sequenceMetadatas =
jdbcEnvironment.getExistingSequenceMetadataExtractor().extractMetadata( databaseMetaData );
private Map<ObjectName,SequenceInformation> loadSequenceMetadataMap() throws SQLException {
Map<ObjectName,SequenceInformation> sequences = new HashMap<ObjectName, SequenceInformation>();
// todo : temporary impl!
final Iterable<SequenceInformation> sequenceMetadatas =
new TemporarySequenceInformationExtractor( jdbcEnvironment ).extractMetadata( databaseMetaData );
if ( sequenceMetadatas != null ) {
for ( ExistingSequenceMetadata sequenceMetadata :sequenceMetadatas ) {
sequences.put( toMapKey( sequenceMetadata.getSequenceName() ), sequenceMetadata );
for ( SequenceInformation sequenceInformation :sequenceMetadatas ) {
sequences.put( toMapKey( sequenceInformation.getSequenceName() ), sequenceInformation );
}
}
return sequences;
}
@Override
public ExistingTableMetadata getTableMetadata(ObjectName tableName) {
public TableInformation getTableInformation(ObjectName tableName) {
return tables.get( toMapKey( tableName ) );
}
@ -144,18 +145,18 @@ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData {
}
@Override
public ExistingSequenceMetadata getSequenceMetadata(ObjectName sequenceName) {
public SequenceInformation getSequenceInformation(ObjectName sequenceName) {
return sequences.get( toMapKey( sequenceName ) );
}
public Map<Identifier, ExistingColumnMetadata> getColumnMetadata(ExistingTableMetadata tableMetadata) {
final Map<Identifier, ExistingColumnMetadata> results = new HashMap<Identifier, ExistingColumnMetadata>();
public Map<Identifier, ColumnInformation> getColumnMetadata(TableInformation tableInformation) {
final Map<Identifier, ColumnInformation> results = new HashMap<Identifier, ColumnInformation>();
try {
ResultSet resultSet = databaseMetaData.getColumns(
identifierHelper().toMetaDataCatalogName( tableMetadata.getName().getCatalog() ),
identifierHelper().toMetaDataSchemaName( tableMetadata.getName().getSchema() ),
identifierHelper().toMetaDataObjectName( tableMetadata.getName().getName() ),
identifierHelper().toMetaDataCatalogName( tableInformation.getName().getCatalog() ),
identifierHelper().toMetaDataSchemaName( tableInformation.getName().getSchema() ),
identifierHelper().toMetaDataObjectName( tableInformation.getName().getName() ),
"%"
);
@ -171,8 +172,8 @@ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData {
continue;
}
final ExistingColumnMetadataImpl meta = new ExistingColumnMetadataImpl(
tableMetadata,
final ColumnInformationImpl meta = new ColumnInformationImpl(
tableInformation,
columnIdentifier,
resultSet.getInt( "DATA_TYPE" ),
new StringTokenizer( resultSet.getString( "TYPE_NAME" ), "() " ).nextToken(),
@ -190,16 +191,16 @@ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData {
catch (SQLException e) {
throw jdbcEnvironment.getSqlExceptionHelper().convert(
e,
"Error accessing column metadata: " + tableMetadata.getName().toString()
"Error accessing column metadata: " + tableInformation.getName().toString()
);
}
return results;
}
public Map<Identifier, ExistingForeignKeyMetadataImpl> getForeignKeyMetadata(ExistingTableMetadataImpl tableMetadata) {
final Map<Identifier, ExistingForeignKeyMetadataImpl.Builder> fkBuilders
= new HashMap<Identifier, ExistingForeignKeyMetadataImpl.Builder>();
public Map<Identifier, ForeignKeyInformationImpl> getForeignKeyMetadata(TableInformationImpl tableMetadata) {
final Map<Identifier, ForeignKeyInformationImpl.Builder> fkBuilders
= new HashMap<Identifier, ForeignKeyInformationImpl.Builder>();
try {
ResultSet resultSet = databaseMetaData.getImportedKeys(
@ -214,15 +215,15 @@ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData {
while ( resultSet.next() ) {
// IMPL NOTE : intentionally build the builder early!
final Identifier fkIdentifier = Identifier.toIdentifier( resultSet.getString( "FK_NAME" ) );
ExistingForeignKeyMetadataImpl.Builder fkBuilder = fkBuilders.get( fkIdentifier );
ForeignKeyInformationImpl.Builder fkBuilder = fkBuilders.get( fkIdentifier );
if ( fkBuilder == null ) {
fkBuilder = ExistingForeignKeyMetadataImpl.builder( fkIdentifier );
fkBuilder = ForeignKeyInformationImpl.builder( fkIdentifier );
fkBuilders.put( fkIdentifier, fkBuilder );
}
final ObjectName incomingPkTableName = extractKeyTableName( resultSet, "PK" );
final ExistingTableMetadataImpl pkTableMetadata = tables.get( incomingPkTableName );
final TableInformationImpl pkTableMetadata = tables.get( incomingPkTableName );
if ( pkTableMetadata == null ) {
// the assumption here is that we have not seen this table already based on fully-qualified name
// during previous step of building all table metadata so most likely this is
@ -235,8 +236,8 @@ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData {
final Identifier pkColumnIdentifier = Identifier.toIdentifier( resultSet.getString( "PKCOLUMN_NAME" ) );
fkBuilder.addColumnMapping(
tableMetadata.getColumnMetadata( fkColumnIdentifier ),
pkTableMetadata.getColumnMetadata( pkColumnIdentifier )
tableMetadata.getColumnInformation( fkColumnIdentifier ),
pkTableMetadata.getColumnInformation( pkColumnIdentifier )
);
}
}
@ -251,9 +252,9 @@ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData {
);
}
final Map<Identifier, ExistingForeignKeyMetadataImpl> fks = new HashMap<Identifier, ExistingForeignKeyMetadataImpl>();
for ( ExistingForeignKeyMetadataImpl.Builder fkBuilder : fkBuilders.values() ) {
ExistingForeignKeyMetadataImpl fk = fkBuilder.build();
final Map<Identifier, ForeignKeyInformationImpl> fks = new HashMap<Identifier, ForeignKeyInformationImpl>();
for ( ForeignKeyInformationImpl.Builder fkBuilder : fkBuilders.values() ) {
ForeignKeyInformationImpl fk = fkBuilder.build();
fks.put( fk.getForeignKeyIdentifier(), fk );
}
return fks;
@ -285,14 +286,14 @@ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData {
public Builder prepareCatalogAndSchema(Schema.Name schemaName);
public Builder prepareCatalog(Identifier catalog);
public Builder prepareSchema(Identifier schema);
public ExistingDatabaseMetaData build();
public DatabaseInformation build();
}
private static class BuilderImpl implements Builder {
private final ExistingDatabaseMetaDataImpl it;
private final DatabaseInformationImpl it;
public BuilderImpl(JdbcEnvironment jdbcEnvironment, DatabaseMetaData databaseMetaData) throws SQLException {
it = new ExistingDatabaseMetaDataImpl( jdbcEnvironment, databaseMetaData );
it = new DatabaseInformationImpl( jdbcEnvironment, databaseMetaData );
}
@Override
@ -355,7 +356,7 @@ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData {
}
@Override
public ExistingDatabaseMetaData build() {
public DatabaseInformation build() {
return it;
}
}

View File

@ -27,18 +27,18 @@ import java.util.ArrayList;
import java.util.List;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.service.schema.spi.ExistingColumnMetadata;
import org.hibernate.service.schema.spi.ExistingForeignKeyMetadata;
import org.hibernate.service.schema.spi.ColumnInformation;
import org.hibernate.service.schema.spi.ForeignKeyInformation;
import org.hibernate.service.schema.spi.SchemaManagementException;
/**
* @author Steve Ebersole
*/
public class ExistingForeignKeyMetadataImpl implements ExistingForeignKeyMetadata {
public class ForeignKeyInformationImpl implements ForeignKeyInformation {
private final Identifier fkIdentifier;
private final List<ColumnReferenceMapping> columnMappingList;
public ExistingForeignKeyMetadataImpl(
public ForeignKeyInformationImpl(
Identifier fkIdentifier,
List<ColumnReferenceMapping> columnMappingList) {
this.fkIdentifier = fkIdentifier;
@ -67,38 +67,38 @@ public class ExistingForeignKeyMetadataImpl implements ExistingForeignKeyMetadat
this.fkIdentifier = fkIdentifier;
}
public Builder addColumnMapping(ExistingColumnMetadata referencing, ExistingColumnMetadata referenced) {
public Builder addColumnMapping(ColumnInformation referencing, ColumnInformation referenced) {
columnMappingList.add( new ColumnReferenceMappingImpl( referencing, referenced ) );
return this;
}
public ExistingForeignKeyMetadataImpl build() {
public ForeignKeyInformationImpl build() {
if ( columnMappingList.isEmpty() ) {
throw new SchemaManagementException(
"Attempt to resolve foreign key metadata from JDBC metadata failed to find " +
"column mappings for foreign key named [" + fkIdentifier.getText() + "]"
);
}
return new ExistingForeignKeyMetadataImpl( fkIdentifier, columnMappingList );
return new ForeignKeyInformationImpl( fkIdentifier, columnMappingList );
}
}
public static class ColumnReferenceMappingImpl implements ColumnReferenceMapping {
private final ExistingColumnMetadata referencing;
private final ExistingColumnMetadata referenced;
private final ColumnInformation referencing;
private final ColumnInformation referenced;
public ColumnReferenceMappingImpl(ExistingColumnMetadata referencing, ExistingColumnMetadata referenced) {
public ColumnReferenceMappingImpl(ColumnInformation referencing, ColumnInformation referenced) {
this.referencing = referencing;
this.referenced = referenced;
}
@Override
public ExistingColumnMetadata getReferencingColumnMetadata() {
public ColumnInformation getReferencingColumnMetadata() {
return referencing;
}
@Override
public ExistingColumnMetadata getReferencedColumnMetadata() {
public ColumnInformation getReferencedColumnMetadata() {
return referenced;
}
}

View File

@ -27,9 +27,9 @@ import org.hibernate.metamodel.spi.relational.Database;
import org.hibernate.metamodel.spi.relational.Schema;
import org.hibernate.metamodel.spi.relational.Sequence;
import org.hibernate.metamodel.spi.relational.Table;
import org.hibernate.service.schema.spi.ExistingDatabaseMetaData;
import org.hibernate.service.schema.spi.ExistingSequenceMetadata;
import org.hibernate.service.schema.spi.ExistingTableMetadata;
import org.hibernate.service.schema.spi.DatabaseInformation;
import org.hibernate.service.schema.spi.SequenceInformation;
import org.hibernate.service.schema.spi.TableInformation;
import org.hibernate.service.schema.spi.SchemaValidator;
/**
@ -37,31 +37,31 @@ import org.hibernate.service.schema.spi.SchemaValidator;
*/
public class SchemaValidatorImpl implements SchemaValidator {
@Override
public void doValidation(Database database, ExistingDatabaseMetaData existingDatabaseMetaData) {
public void doValidation(Database database, DatabaseInformation databaseInformation) {
for ( Schema schema : database.getSchemas() ) {
for ( Table table : schema.getTables() ) {
final ExistingTableMetadata existingTableMetadata = existingDatabaseMetaData.getTableMetadata(
final TableInformation tableInformation = databaseInformation.getTableInformation(
table.getTableName()
);
validateTable( table, existingTableMetadata );
validateTable( table, tableInformation );
}
}
for ( Schema schema : database.getSchemas() ) {
for ( Sequence sequence : schema.getSequences() ) {
final ExistingSequenceMetadata existingSequenceMetadata = existingDatabaseMetaData.getSequenceMetadata(
final SequenceInformation sequenceInformation = databaseInformation.getSequenceInformation(
sequence.getName()
);
validateSequence( sequence, existingSequenceMetadata );
validateSequence( sequence, sequenceInformation );
}
}
}
private void validateTable(Table table, ExistingTableMetadata existingTableMetadata) {
private void validateTable(Table table, TableInformation tableInformation) {
//To change body of created methods use File | Settings | File Templates.
}
private void validateSequence(Sequence sequence, ExistingSequenceMetadata existingSequenceMetadata) {
private void validateSequence(Sequence sequence, SequenceInformation sequenceInformation) {
//To change body of created methods use File | Settings | File Templates.
}
}

View File

@ -24,17 +24,17 @@
package org.hibernate.service.schema.internal;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.service.schema.spi.ExistingSequenceMetadata;
import org.hibernate.service.schema.spi.SequenceInformation;
/**
* For now we only collect sequence name. If all databases support it, would really like to see INCREMENT here as well.
*
* @author Steve Ebersole
*/
public class ExistingSequenceMetadataImpl implements ExistingSequenceMetadata {
public class SequenceInformationImpl implements SequenceInformation {
private ObjectName sequenceName;
public ExistingSequenceMetadataImpl(ObjectName sequenceName) {
public SequenceInformationImpl(ObjectName sequenceName) {
this.sequenceName = sequenceName;
}

View File

@ -25,12 +25,11 @@ package org.hibernate.service.schema.internal;
import java.util.Map;
import org.hibernate.metamodel.spi.relational.ForeignKey;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.service.schema.spi.ExistingColumnMetadata;
import org.hibernate.service.schema.spi.ExistingForeignKeyMetadata;
import org.hibernate.service.schema.spi.ExistingTableMetadata;
import org.hibernate.service.schema.spi.ColumnInformation;
import org.hibernate.service.schema.spi.ForeignKeyInformation;
import org.hibernate.service.schema.spi.TableInformation;
import org.hibernate.tool.hbm2ddl.IndexMetadata;
/**
@ -40,14 +39,14 @@ import org.hibernate.tool.hbm2ddl.IndexMetadata;
* @author Max Rydahl Andersen
* @author Steve Ebersole
*/
public class ExistingTableMetadataImpl implements ExistingTableMetadata {
private final ExistingDatabaseMetaDataImpl database;
public class TableInformationImpl implements TableInformation {
private final DatabaseInformationImpl database;
private final ObjectName tableName;
private final Map<Identifier, ExistingColumnMetadata> columns;
private final Map<Identifier, ColumnInformation> columns;
private Map<Identifier, ExistingForeignKeyMetadataImpl> foreignKeys;
private Map<Identifier, ForeignKeyInformationImpl> foreignKeys;
public ExistingTableMetadataImpl(ExistingDatabaseMetaDataImpl database, ObjectName tableName) {
public TableInformationImpl(DatabaseInformationImpl database, ObjectName tableName) {
this.database = database;
this.tableName = tableName;
this.columns = database.getColumnMetadata( this );
@ -59,12 +58,12 @@ public class ExistingTableMetadataImpl implements ExistingTableMetadata {
}
@Override
public ExistingColumnMetadata getColumnMetadata(Identifier columnIdentifier) {
public ColumnInformation getColumnInformation(Identifier columnIdentifier) {
return columns.get( columnIdentifier );
}
@Override
public ExistingForeignKeyMetadata getForeignKeyMetadata(Identifier fkIdentifier) {
public ForeignKeyInformation getForeignKeyInformation(Identifier fkIdentifier) {
if ( foreignKeys == null ) {
foreignKeys = database.getForeignKeyMetadata( this );
}
@ -72,20 +71,14 @@ public class ExistingTableMetadataImpl implements ExistingTableMetadata {
}
@Override
public ExistingForeignKeyMetadata getForeignKeyMetadata(ForeignKey fk) {
// Iterator it = foreignKeys.values().iterator();
// while ( it.hasNext() ) {
// ForeignKeyMetadata existingFk = ( ForeignKeyMetadata ) it.next();
// if ( existingFk.matches( fk ) ) {
// return existingFk;
// }
// }
return null;
@SuppressWarnings("unchecked")
public Iterable getForeignKeyInformations() {
return foreignKeys.values();
}
@Override
public String toString() {
return "ExistingTableMetadataImpl(" + tableName.toString() + ')';
return "TableInformationImpl(" + tableName.toString() + ')';
}
@Override

View File

@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.env.internal;
package org.hibernate.service.schema.internal;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
@ -31,24 +31,24 @@ import java.util.ArrayList;
import java.util.List;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.service.schema.internal.ExistingSequenceMetadataImpl;
import org.hibernate.service.schema.spi.ExistingSequenceMetadata;
import org.hibernate.service.schema.spi.ExistingSequenceMetadataExtractor;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.schema.spi.SequenceInformation;
import org.hibernate.service.schema.spi.SequenceInformationExtractor;
/**
* Temporary implementation that works for H2.
*
* @author Steve Ebersole
*/
public class TemporaryExistingSequenceMetadataExtractor implements ExistingSequenceMetadataExtractor {
private final JdbcEnvironmentImpl jdbcEnvironment;
public class TemporarySequenceInformationExtractor implements SequenceInformationExtractor {
private final JdbcEnvironment jdbcEnvironment;
public TemporaryExistingSequenceMetadataExtractor(JdbcEnvironmentImpl jdbcEnvironment) {
public TemporarySequenceInformationExtractor(JdbcEnvironment jdbcEnvironment) {
this.jdbcEnvironment = jdbcEnvironment;
}
@Override
public Iterable<ExistingSequenceMetadata> extractMetadata(DatabaseMetaData databaseMetaData) throws SQLException {
public Iterable<SequenceInformation> extractMetadata(DatabaseMetaData databaseMetaData) throws SQLException {
Statement statement = databaseMetaData.getConnection().createStatement();
try {
ResultSet resultSet = statement.executeQuery(
@ -56,10 +56,10 @@ public class TemporaryExistingSequenceMetadataExtractor implements ExistingSeque
"from information_schema.sequences"
);
try {
final List<ExistingSequenceMetadata> sequenceMetadataList = new ArrayList<ExistingSequenceMetadata>();
final List<SequenceInformation> sequenceInformationList = new ArrayList<SequenceInformation>();
while ( resultSet.next() ) {
sequenceMetadataList.add(
new ExistingSequenceMetadataImpl(
sequenceInformationList.add(
new SequenceInformationImpl(
new ObjectName(
jdbcEnvironment.getIdentifierHelper().fromMetaDataCatalogName(
resultSet.getString(
@ -80,7 +80,7 @@ public class TemporaryExistingSequenceMetadataExtractor implements ExistingSeque
)
);
}
return sequenceMetadataList;
return sequenceInformationList;
}
finally {
try {

View File

@ -0,0 +1,92 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.schema.spi;
import org.hibernate.TruthValue;
import org.hibernate.metamodel.spi.relational.Identifier;
/**
* Provides access to information about existing table columns
*
* @author Christoph Sturm
* @author Steve Ebersole
*/
public interface ColumnInformation {
/**
* Access to the containing table.
*
* @return The containing table information
*/
public TableInformation getContainingTableInformation();
/**
* The simple (not qualified) column name.
*
* @return The column simple identifier.
*/
public Identifier getColumnIdentifier();
/**
* Is the column nullable. The database is allowed to report unknown, hence the use of TruthValue
*
* @return nullability.
*/
public TruthValue getNullable();
/**
* The JDBC type-code.
*
* @return JDBC type-code
*/
public int getTypeCode();
/**
* The database specific type name.
*
* @return Type name
*/
public String getTypeName();
// todo : wrap these in org.hibernate.metamodel.spi.relational.Size ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* The column size (length).
*
* @return The column length
*/
public int getColumnSize();
/**
* The precision, for numeric types
*
* @return The numeric precision
*/
public int getDecimalDigits();
}

View File

@ -23,27 +23,31 @@
*/
package org.hibernate.service.schema.spi;
import org.hibernate.metamodel.spi.relational.ForeignKey;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.tool.hbm2ddl.ForeignKeyMetadata;
import org.hibernate.tool.hbm2ddl.IndexMetadata;
/**
* Provides access to information about existing schema objects (tables, sequences etc) of existing database.
*
* @author Christoph Sturm
* @author Max Rydahl Andersen
* @author Teodor Danciu
* @author Steve Ebersole
*/
public interface ExistingTableMetadata {
public ObjectName getName();
public interface DatabaseInformation {
/**
* Obtain reference to the named TableInformation
*
* @param tableName The qualified table name
*
* @return The table information. May return {@code null} if not found.
*/
public TableInformation getTableInformation(ObjectName tableName);
public ExistingColumnMetadata getColumnMetadata(Identifier columnIdentifier);
public ExistingForeignKeyMetadata getForeignKeyMetadata(Identifier keyName);
public ExistingForeignKeyMetadata getForeignKeyMetadata(ForeignKey fk);
public IndexMetadata getIndexMetadata(Identifier indexName);
/**
* Obtain reference to the named SequenceInformation
*
* @param sequenceName The qualified sequence name
*
* @return The sequence information. May return {@code null} if not found.
*/
public SequenceInformation getSequenceInformation(ObjectName sequenceName);
}

View File

@ -30,7 +30,7 @@ import org.hibernate.metamodel.spi.relational.Identifier;
/**
* @author Steve Ebersole
*/
public interface ExistingForeignKeyMetadata {
public interface ForeignKeyInformation {
/**
* Obtain the identifier for this FK.
*
@ -52,13 +52,13 @@ public interface ExistingForeignKeyMetadata {
*
* @return The referencing column.
*/
public ExistingColumnMetadata getReferencingColumnMetadata();
public ColumnInformation getReferencingColumnMetadata();
/**
* Obtain the information about the referenced column (the target side).
*
* @return The referenced column
*/
public ExistingColumnMetadata getReferencedColumnMetadata();
public ColumnInformation getReferencedColumnMetadata();
}
}

View File

@ -42,5 +42,5 @@ public interface SchemaMigrator {
*
* @throws SchemaManagementException
*/
public void doMigration(Database database, ExistingDatabaseMetaData existingDatabase, List<Target> targets) throws SchemaManagementException;
public void doMigration(Database database, DatabaseInformation existingDatabase, List<Target> targets) throws SchemaManagementException;
}

View File

@ -35,9 +35,9 @@ public interface SchemaValidator {
* Handle schema validation requests
*
* @param database The current Hibernate relational model
* @param existingDatabaseMetaData Access to the existing database information.
* @param databaseInformation Access to the existing database information.
*
* @throws SchemaManagementException
*/
public void doValidation(Database database, ExistingDatabaseMetaData existingDatabaseMetaData) throws SchemaManagementException;
public void doValidation(Database database, DatabaseInformation databaseInformation) throws SchemaManagementException;
}

View File

@ -26,13 +26,18 @@ package org.hibernate.service.schema.spi;
import org.hibernate.metamodel.spi.relational.ObjectName;
/**
* Provides access to information about existing schema objects (tables, sequences etc) of existing database.
* Access to information about existing sequences.
*
* For now we only support retrieving the names (for existence checking from validation). However,
* at least INCREMENT would be valuable as well. Just need to make sure all dbs support that.
*
* @author Christoph Sturm
* @author Teodor Danciu
* @author Steve Ebersole
*/
public interface ExistingDatabaseMetaData {
public ExistingTableMetadata getTableMetadata(ObjectName tableName);
public ExistingSequenceMetadata getSequenceMetadata(ObjectName sequenceName);
public interface SequenceInformation {
/**
* The qualified sequence name.
*
* @return The sequence name
*/
public ObjectName getSequenceName();
}

View File

@ -0,0 +1,47 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.schema.spi;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
/**
* Because JDBC (at least up to an including Java 7, JDBC 4) still does not have support for obtaining information
* about sequences from DatabaseMetaData.
*
* @author Steve Ebersole
*/
public interface SequenceInformationExtractor {
/**
* Get the information about sequences.
*
* @param databaseMetaData The JDBC DatabaseMetadata
*
* @return The extracted information about existing sequences.
*
* @throws SQLException Don't bother handling SQLExceptions (unless you want to), we will deal with them in the
* caller.
*/
public Iterable<SequenceInformation> extractMetadata(DatabaseMetaData databaseMetaData) throws SQLException;
}

View File

@ -0,0 +1,75 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.schema.spi;
import org.hibernate.metamodel.spi.relational.ForeignKey;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.tool.hbm2ddl.IndexMetadata;
/**
* Provides access to information about existing tables in the database
*
* @author Christoph Sturm
* @author Max Rydahl Andersen
* @author Steve Ebersole
*/
public interface TableInformation {
/**
* Get the qualified name of the table.
*
* @return The qualified table name
*/
public ObjectName getName();
/**
* Retrieve the named ColumnInformation
*
* @param columnIdentifier The column identifier (simple name)
*
* @return The matching column information. May return {@code null}
*/
public ColumnInformation getColumnInformation(Identifier columnIdentifier);
/**
* Retrieve the named ForeignKeyInformation
*
* @param keyName The foreign key identifier (simple name)
*
* @return The matching foreign key information. May return {@code null}
*/
public ForeignKeyInformation getForeignKeyInformation(Identifier keyName);
/**
* Obtain an iterable over all the table's defined foreign keys.
*
* @return The iterable.
*/
public Iterable<ForeignKeyInformation> getForeignKeyInformations();
/**
* todo : create an IndexInformation...
*/
public IndexMetadata getIndexMetadata(Identifier indexName);
}

View File

@ -50,7 +50,7 @@ import org.hibernate.engine.jdbc.NClobImplementer;
import org.hibernate.engine.jdbc.NonContextualLobCreator;
import org.hibernate.engine.jdbc.WrappedBlob;
import org.hibernate.engine.jdbc.WrappedClob;
import org.hibernate.engine.jdbc.internal.LobCreatorBuilder;
import org.hibernate.service.jdbc.env.internal.LobCreatorBuilderImpl;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
@ -65,8 +65,7 @@ public class LobCreatorTest extends org.hibernate.testing.junit4.BaseUnitTestCas
final Connection connection = createConnectionProxy( 4, new JdbcLobBuilderImpl( true ) );
LobCreationContext lobCreationContext = new LobCreationContextImpl( connection );
LobCreator lobCreator =
new LobCreatorBuilder( new Properties(), connection )
LobCreator lobCreator = LobCreatorBuilderImpl.makeLobCreatorBuilder( new Properties(), connection )
.buildLobCreator( lobCreationContext );
assertTrue( lobCreator instanceof ContextualLobCreator );
testLobCreation( lobCreator );
@ -78,8 +77,7 @@ public class LobCreatorTest extends org.hibernate.testing.junit4.BaseUnitTestCas
final Connection connection = createConnectionProxy( 3, new JdbcLobBuilderImpl( false) );
LobCreationContext lobCreationContext = new LobCreationContextImpl( connection );
LobCreator lobCreator =
new LobCreatorBuilder( new Properties(), connection )
LobCreator lobCreator = LobCreatorBuilderImpl.makeLobCreatorBuilder( new Properties(), connection )
.buildLobCreator( lobCreationContext );
assertSame( NonContextualLobCreator.INSTANCE, lobCreator );
@ -91,8 +89,7 @@ public class LobCreatorTest extends org.hibernate.testing.junit4.BaseUnitTestCas
final Connection connection = createConnectionProxy( 4, new JdbcLobBuilderImpl( false ) );
LobCreationContext lobCreationContext = new LobCreationContextImpl( connection );
LobCreator lobCreator =
new LobCreatorBuilder( new Properties(), connection )
LobCreator lobCreator = LobCreatorBuilderImpl.makeLobCreatorBuilder( new Properties(), connection )
.buildLobCreator( lobCreationContext );
assertSame( NonContextualLobCreator.INSTANCE, lobCreator );
@ -106,8 +103,7 @@ public class LobCreatorTest extends org.hibernate.testing.junit4.BaseUnitTestCas
Properties props = new Properties();
props.setProperty( Environment.NON_CONTEXTUAL_LOB_CREATION, "true" );
LobCreator lobCreator =
new LobCreatorBuilder( props, connection )
LobCreator lobCreator = LobCreatorBuilderImpl.makeLobCreatorBuilder( props, connection )
.buildLobCreator( lobCreationContext );
assertSame( NonContextualLobCreator.INSTANCE, lobCreator );

View File

@ -24,22 +24,28 @@
package org.hibernate.test.common;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.engine.jdbc.internal.ResultSetWrapperImpl;
import org.hibernate.engine.jdbc.internal.TypeInfo;
import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.ResultSetWrapper;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.service.jdbc.env.internal.ExtractedDatabaseMetaDataImpl;
import org.hibernate.service.jdbc.env.internal.LobCreatorBuilderImpl;
import org.hibernate.service.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.service.jdbc.env.spi.IdentifierHelper;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.jdbc.env.spi.LobCreatorBuilder;
import org.hibernate.service.jdbc.env.spi.QualifiedObjectNameSupport;
import org.hibernate.service.spi.Stoppable;
import org.hibernate.testing.env.ConnectionProviderBuilder;
@ -50,11 +56,9 @@ import org.hibernate.testing.env.ConnectionProviderBuilder;
* @author Steve Ebersole
*/
public class BasicTestingJdbcServiceImpl implements JdbcServices {
private ConnectionProvider connectionProvider;
private Dialect dialect;
private SqlStatementLogger sqlStatementLogger;
private SqlExceptionHelper exceptionHelper;
private final ExtractedDatabaseMetaData metaDataSupport = new MetaDataSupportImpl();
private TestingJdbcEnvironmentImpl jdbcEnvironment;
private final SqlStatementLogger sqlStatementLogger = new SqlStatementLogger( true, false );
private final ResultSetWrapper resultSetWrapper = ResultSetWrapperImpl.INSTANCE;
public void start() {
@ -65,38 +69,34 @@ public class BasicTestingJdbcServiceImpl implements JdbcServices {
}
public void prepare(boolean allowAggressiveRelease) {
connectionProvider = ConnectionProviderBuilder.buildConnectionProvider( allowAggressiveRelease );
dialect = ConnectionProviderBuilder.getCorrespondingDialect();
sqlStatementLogger = new SqlStatementLogger( true, false );
exceptionHelper = new SqlExceptionHelper();
jdbcEnvironment = new TestingJdbcEnvironmentImpl( allowAggressiveRelease );
}
public void release() {
if ( connectionProvider instanceof Stoppable ) {
( (Stoppable) connectionProvider ).stop();
if ( jdbcEnvironment.connectionProvider instanceof Stoppable ) {
( (Stoppable) jdbcEnvironment.connectionProvider ).stop();
}
}
public ConnectionProvider getConnectionProvider() {
return connectionProvider;
return jdbcEnvironment.connectionProvider;
}
public Dialect getDialect() {
return dialect;
return jdbcEnvironment.dialect;
}
public LobCreator getLobCreator(LobCreationContext lobCreationContext) {
return null;
return jdbcEnvironment.getLobCreatorBuilder().buildLobCreator( lobCreationContext );
}
public ResultSetWrapper getResultSetWrapper() {
return null;
return resultSetWrapper;
}
@Override
public JdbcEnvironment getJdbcEnvironment() {
return null;
return jdbcEnvironment;
}
public SqlStatementLogger getSqlStatementLogger() {
@ -104,68 +104,72 @@ public class BasicTestingJdbcServiceImpl implements JdbcServices {
}
public SqlExceptionHelper getSqlExceptionHelper() {
return exceptionHelper;
return jdbcEnvironment.exceptionHelper;
}
public ExtractedDatabaseMetaData getExtractedMetaDataSupport() {
return metaDataSupport;
return jdbcEnvironment.extractedDatabaseMetaData;
}
private static class MetaDataSupportImpl implements ExtractedDatabaseMetaData {
@Override
public boolean supportsRefCursors() {
return false;
private static class TestingJdbcEnvironmentImpl implements JdbcEnvironment {
private final ExtractedDatabaseMetaData extractedDatabaseMetaData = new ExtractedDatabaseMetaDataImpl( this );
private final SqlExceptionHelper exceptionHelper = new SqlExceptionHelper();
private final LobCreatorBuilder lobCreatorBuilder = LobCreatorBuilderImpl.makeLobCreatorBuilder();
private ConnectionProvider connectionProvider;
private Dialect dialect;
private TestingJdbcEnvironmentImpl(boolean allowAggressiveRelease) {
connectionProvider = ConnectionProviderBuilder.buildConnectionProvider( allowAggressiveRelease );
dialect = ConnectionProviderBuilder.getCorrespondingDialect();
}
@Override
public boolean supportsNamedParameters() {
return false;
public Dialect getDialect() {
return dialect;
}
public boolean supportsScrollableResults() {
return false;
@Override
public ExtractedDatabaseMetaData getExtractedDatabaseMetaData() {
return extractedDatabaseMetaData;
}
public boolean supportsGetGeneratedKeys() {
return false;
@Override
public Identifier getCurrentCatalog() {
return null;
}
public boolean supportsBatchUpdates() {
return false;
@Override
public Identifier getCurrentSchema() {
return null;
}
public boolean supportsDataDefinitionInTransaction() {
return false;
@Override
public QualifiedObjectNameSupport getQualifiedObjectNameSupport() {
return null;
}
public boolean doesDataDefinitionCauseTransactionCommit() {
return false;
@Override
public IdentifierHelper getIdentifierHelper() {
return null;
}
public Set<String> getExtraKeywords() {
@Override
public Set<String> getReservedWords() {
return Collections.emptySet();
}
public SQLStateType getSqlStateType() {
return SQLStateType.UNKOWN;
@Override
public SqlExceptionHelper getSqlExceptionHelper() {
return exceptionHelper;
}
public boolean doesLobLocatorUpdateCopy() {
return false;
}
public String getConnectionSchemaName() {
return null;
}
public String getConnectionCatalogName() {
return null;
}
public LinkedHashSet<TypeInfo> getTypeInfoSet() {
return null;
@Override
public LobCreatorBuilder getLobCreatorBuilder() {
return lobCreatorBuilder;
}
@Override
public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode) {
return null;
}

View File

@ -26,7 +26,7 @@ package org.hibernate.test.common;
import java.sql.Connection;
import java.sql.SQLException;
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
import org.hibernate.service.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.transaction.spi.TransactionEnvironment;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
@ -58,4 +58,9 @@ public class JdbcConnectionAccessImpl implements JdbcConnectionAccess {
public void releaseConnection(Connection connection) throws SQLException {
connectionProvider.closeConnection( connection );
}
@Override
public boolean supportsAggressiveRelease() {
return connectionProvider.supportsAggressiveRelease();
}
}

View File

@ -24,7 +24,7 @@
package org.hibernate.test.common;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
import org.hibernate.service.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.transaction.spi.TransactionContext;
import org.hibernate.engine.transaction.spi.TransactionEnvironment;
import org.hibernate.engine.transaction.spi.TransactionImplementor;

View File

@ -23,7 +23,7 @@
*/
package org.hibernate.test.engine.jdbc.env;
import org.hibernate.engine.jdbc.env.spi.StandardSchemaCatalogSupportImpl;
import org.hibernate.service.jdbc.env.spi.StandardQualifiedObjectNameSupportImpl;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.junit.Test;
@ -37,8 +37,8 @@ import static org.junit.Assert.assertNull;
* @author Steve Ebersole
*/
public class StandardSchemaCatalogSupportImplTest extends BaseUnitTestCase {
private final StandardSchemaCatalogSupportImpl basic = new StandardSchemaCatalogSupportImpl();
private final StandardSchemaCatalogSupportImpl oracle = new StandardSchemaCatalogSupportImpl( "@", true );
private final StandardQualifiedObjectNameSupportImpl basic = new StandardQualifiedObjectNameSupportImpl();
private final StandardQualifiedObjectNameSupportImpl oracle = new StandardQualifiedObjectNameSupportImpl( "@", true );
@Test
public void testFormatName() throws Exception {

View File

@ -30,11 +30,13 @@ import java.util.Properties;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.ServiceRegistryBuilder;
import org.hibernate.service.jdbc.env.internal.JdbcEnvironmentImpl;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.service.schema.internal.ExistingDatabaseMetaDataImpl;
import org.hibernate.service.schema.spi.ExistingDatabaseMetaData;
import org.hibernate.service.schema.internal.DatabaseInformationImpl;
import org.hibernate.service.schema.spi.DatabaseInformation;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.junit.After;
import org.junit.Before;
@ -48,12 +50,14 @@ import static org.junit.Assert.assertNotNull;
* @author Steve Ebersole
*/
public class ExistingDatabaseMetaDataImplTest extends BaseUnitTestCase {
private ServiceRegistryImplementor serviceRegistry;
private JdbcEnvironment jdbcEnvironment;
private Connection connection;
@Before
public void prepare() throws SQLException {
Properties props = Environment.getProperties();
serviceRegistry = (ServiceRegistryImplementor) new ServiceRegistryBuilder().applySettings( props ).buildServiceRegistry();
connection = DriverManager.getConnection(
props.getProperty( Environment.URL ),
props.getProperty( Environment.USER ),
@ -67,7 +71,7 @@ public class ExistingDatabaseMetaDataImplTest extends BaseUnitTestCase {
connection.createStatement().execute( "CREATE SEQUENCE seq1" );
connection.createStatement().execute( "CREATE SEQUENCE db1.another_schema.seq2" );
jdbcEnvironment = new JdbcEnvironmentImpl( connection.getMetaData(), Dialect.getDialect( props ), props );
jdbcEnvironment = new JdbcEnvironmentImpl( serviceRegistry, Dialect.getDialect( props ), connection.getMetaData() );
}
@After
@ -79,27 +83,30 @@ public class ExistingDatabaseMetaDataImplTest extends BaseUnitTestCase {
catch (SQLException ignore) {
}
}
if ( serviceRegistry != null ) {
ServiceRegistryBuilder.destroy( serviceRegistry );
}
}
@Test
public void testGetTableMetadata() throws Exception {
ExistingDatabaseMetaData databaseMetaData =
ExistingDatabaseMetaDataImpl.builder( jdbcEnvironment, connection.getMetaData() ).prepareAll().build();
DatabaseInformation databaseMetaData =
DatabaseInformationImpl.builder( jdbcEnvironment, connection.getMetaData() ).prepareAll().build();
ObjectName name = new ObjectName( null, null, "t1" );
assertNotNull( databaseMetaData.getTableMetadata( name ) );
assertNotNull( databaseMetaData.getTableInformation( name ) );
name = new ObjectName( null, "another_schema", "t2" );
assertNotNull( databaseMetaData.getTableMetadata( name ) );
assertNotNull( databaseMetaData.getTableInformation( name ) );
name = new ObjectName( null, null, "seq1" );
assertNotNull( databaseMetaData.getSequenceMetadata( name ) );
assertNotNull( databaseMetaData.getSequenceInformation( name ) );
name = new ObjectName( null, "another_schema", "seq2" );
assertNotNull( databaseMetaData.getSequenceMetadata( name ) );
assertNotNull( databaseMetaData.getSequenceInformation( name ) );
// knowing if identifiers coming back from the database are quoted is all dicked up...
// see org.hibernate.engine.jdbc.env.internal.NormalizingIdentifierHelperImpl
// see org.hibernate.service.jdbc.env.internal.NormalizingIdentifierHelperImpl
//
// surely JDBC has a better way to determine this right?
}

View File

@ -38,7 +38,7 @@ import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.cache.spi.CacheKey;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
import org.hibernate.service.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.LoadQueryInfluencers;