HHH-10133 - CatalogSeparator of dialect metadata not used in runtime, just in schema tool
This commit is contained in:
parent
7354c7bfc3
commit
3571218183
|
@ -14,6 +14,11 @@ import org.hibernate.boot.model.naming.Identifier;
|
|||
* <li>{@link java.sql.DatabaseMetaData#isCatalogAtStart}</li>
|
||||
* <li>{@link java.sql.DatabaseMetaData#getCatalogSeparator()}</li>
|
||||
* </ol>
|
||||
* <p/>
|
||||
* Also, be careful about the usage of {@link #render}. If the intention is get get the name
|
||||
* as used in the database, the {@link org.hibernate.engine.jdbc.env.spi.JdbcEnvironment} ->
|
||||
* {@link org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameFormatter#format} should be
|
||||
* used instead.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -22,5 +27,14 @@ public interface QualifiedName {
|
|||
Identifier getSchemaName();
|
||||
Identifier getObjectName();
|
||||
|
||||
/**
|
||||
* Returns a String-form of the qualified name.
|
||||
* <p/>
|
||||
* Depending on intention, may not be appropriate. May want
|
||||
* {@link org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameFormatter#format}
|
||||
* instead. See {@link org.hibernate.engine.jdbc.env.spi.JdbcEnvironment#getQualifiedObjectNameFormatter}
|
||||
*
|
||||
* @return The string form
|
||||
*/
|
||||
String render();
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.hibernate.boot.model.relational.InitCommand;
|
|||
import org.hibernate.boot.model.relational.Namespace;
|
||||
import org.hibernate.boot.model.relational.QualifiedTableName;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameFormatter;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.tool.hbm2ddl.ColumnMetadata;
|
||||
|
@ -106,6 +107,11 @@ public class Table implements RelationalModel, Serializable, Exportable {
|
|||
this.isAbstract = isAbstract;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Should use {@link QualifiedObjectNameFormatter#format} on QualifiedObjectNameFormatter
|
||||
* obtained from {@link org.hibernate.engine.jdbc.env.spi.JdbcEnvironment}
|
||||
*/
|
||||
@Deprecated
|
||||
public String getQualifiedName(Dialect dialect, String defaultCatalog, String defaultSchema) {
|
||||
if ( subselect != null ) {
|
||||
return "( " + subselect + " )";
|
||||
|
@ -120,6 +126,11 @@ public class Table implements RelationalModel, Serializable, Exportable {
|
|||
return qualify( usedCatalog, usedSchema, quotedName );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Should use {@link QualifiedObjectNameFormatter#format} on QualifiedObjectNameFormatter
|
||||
* obtained from {@link org.hibernate.engine.jdbc.env.spi.JdbcEnvironment}
|
||||
*/
|
||||
@Deprecated
|
||||
public static String qualify(String catalog, String schema, String table) {
|
||||
StringBuilder qualifiedName = new StringBuilder();
|
||||
if ( catalog != null ) {
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.TransientObjectException;
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.entry.CacheEntryStructure;
|
||||
|
@ -31,6 +32,7 @@ import org.hibernate.cache.spi.entry.UnstructuredCacheEntry;
|
|||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
||||
import org.hibernate.engine.spi.EntityKey;
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
|
@ -230,9 +232,12 @@ public abstract class AbstractCollectionPersister
|
|||
CollectionRegionAccessStrategy cacheAccessStrategy,
|
||||
PersisterCreationContext creationContext) throws MappingException, CacheException {
|
||||
|
||||
final Database database = creationContext.getMetadata().getDatabase();
|
||||
final JdbcEnvironment jdbcEnvironment = database.getJdbcEnvironment();
|
||||
|
||||
this.factory = creationContext.getSessionFactory();
|
||||
this.cacheAccessStrategy = cacheAccessStrategy;
|
||||
if ( factory.getSettings().isStructuredCacheEntriesEnabled() ) {
|
||||
if ( factory.getSessionFactoryOptions().isStructuredCacheEntriesEnabled() ) {
|
||||
cacheEntryStructure = collectionBinding.isMap()
|
||||
? StructuredMapCacheEntry.INSTANCE
|
||||
: StructuredCollectionCacheEntry.INSTANCE;
|
||||
|
@ -260,11 +265,7 @@ public abstract class AbstractCollectionPersister
|
|||
isArray = collectionBinding.isArray();
|
||||
subselectLoadable = collectionBinding.isSubselectLoadable();
|
||||
|
||||
qualifiedTableName = table.getQualifiedName(
|
||||
dialect,
|
||||
factory.getSettings().getDefaultCatalogName(),
|
||||
factory.getSettings().getDefaultSchemaName()
|
||||
);
|
||||
qualifiedTableName = determineTableName( table, jdbcEnvironment );
|
||||
|
||||
int spacesSize = 1 + collectionBinding.getSynchronizedTables().size();
|
||||
spaces = new String[spacesSize];
|
||||
|
@ -284,7 +285,7 @@ public abstract class AbstractCollectionPersister
|
|||
|
||||
int batch = collectionBinding.getBatchSize();
|
||||
if ( batch == -1 ) {
|
||||
batch = factory.getSettings().getDefaultBatchFetchSize();
|
||||
batch = factory.getSessionFactoryOptions().getDefaultBatchFetchSize();
|
||||
}
|
||||
batchSize = batch;
|
||||
|
||||
|
@ -585,6 +586,17 @@ public abstract class AbstractCollectionPersister
|
|||
initCollectionPropertyMap();
|
||||
}
|
||||
|
||||
protected String determineTableName(Table table, JdbcEnvironment jdbcEnvironment) {
|
||||
if ( table.getSubselect() != null ) {
|
||||
return "( " + table.getSubselect() + " )";
|
||||
}
|
||||
|
||||
return jdbcEnvironment.getQualifiedObjectNameFormatter().format(
|
||||
table.getQualifiedTableName(),
|
||||
jdbcEnvironment.getDialect()
|
||||
);
|
||||
}
|
||||
|
||||
private class ColumnMapperImpl implements ColumnMapper {
|
||||
@Override
|
||||
public SqlValueReference[] map(String reference) {
|
||||
|
|
|
@ -54,6 +54,7 @@ import org.hibernate.engine.internal.MutableEntityEntryFactory;
|
|||
import org.hibernate.engine.internal.StatefulPersistenceContext;
|
||||
import org.hibernate.engine.internal.Versioning;
|
||||
import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.spi.CachedNaturalIdValueSource;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.engine.spi.CascadingActions;
|
||||
|
@ -92,6 +93,7 @@ import org.hibernate.mapping.Component;
|
|||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Selectable;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.metadata.ClassMetadata;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.spi.PersisterCreationContext;
|
||||
|
@ -5112,6 +5114,17 @@ public abstract class AbstractEntityPersister
|
|||
return 0;
|
||||
}
|
||||
|
||||
protected String determineTableName(Table table, JdbcEnvironment jdbcEnvironment) {
|
||||
if ( table.getSubselect() != null ) {
|
||||
return "( " + table.getSubselect() + " )";
|
||||
}
|
||||
|
||||
return jdbcEnvironment.getQualifiedObjectNameFormatter().format(
|
||||
table.getQualifiedTableName(),
|
||||
jdbcEnvironment.getDialect()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityEntryFactory getEntityEntryFactory() {
|
||||
return this.entityEntryFactory;
|
||||
|
|
|
@ -18,9 +18,11 @@ import org.hibernate.AssertionFailure;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.engine.OptimisticLockStyle;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.DynamicFilterAliasGenerator;
|
||||
|
@ -133,6 +135,8 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
super( persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, creationContext );
|
||||
|
||||
final SessionFactoryImplementor factory = creationContext.getSessionFactory();
|
||||
final Database database = creationContext.getMetadata().getDatabase();
|
||||
final JdbcEnvironment jdbcEnvironment = database.getJdbcEnvironment();
|
||||
|
||||
// DISCRIMINATOR
|
||||
|
||||
|
@ -201,28 +205,24 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
final int idColumnSpan = getIdentifierColumnSpan();
|
||||
|
||||
ArrayList tables = new ArrayList();
|
||||
ArrayList keyColumns = new ArrayList();
|
||||
ArrayList keyColumnReaders = new ArrayList();
|
||||
ArrayList keyColumnReaderTemplates = new ArrayList();
|
||||
ArrayList cascadeDeletes = new ArrayList();
|
||||
Iterator titer = persistentClass.getTableClosureIterator();
|
||||
Iterator kiter = persistentClass.getKeyClosureIterator();
|
||||
while ( titer.hasNext() ) {
|
||||
Table tab = (Table) titer.next();
|
||||
KeyValue key = (KeyValue) kiter.next();
|
||||
String tabname = tab.getQualifiedName(
|
||||
factory.getDialect(),
|
||||
factory.getSettings().getDefaultCatalogName(),
|
||||
factory.getSettings().getDefaultSchemaName()
|
||||
);
|
||||
tables.add( tabname );
|
||||
ArrayList<String> tableNames = new ArrayList<String>();
|
||||
ArrayList<String[]> keyColumns = new ArrayList<String[]>();
|
||||
ArrayList<String[]> keyColumnReaders = new ArrayList<String[]>();
|
||||
ArrayList<String[]> keyColumnReaderTemplates = new ArrayList<String[]>();
|
||||
ArrayList<Boolean> cascadeDeletes = new ArrayList<Boolean>();
|
||||
Iterator tItr = persistentClass.getTableClosureIterator();
|
||||
Iterator kItr = persistentClass.getKeyClosureIterator();
|
||||
while ( tItr.hasNext() ) {
|
||||
final Table table = (Table) tItr.next();
|
||||
final KeyValue key = (KeyValue) kItr.next();
|
||||
final String tableName = determineTableName( table, jdbcEnvironment );
|
||||
tableNames.add( tableName );
|
||||
String[] keyCols = new String[idColumnSpan];
|
||||
String[] keyColReaders = new String[idColumnSpan];
|
||||
String[] keyColReaderTemplates = new String[idColumnSpan];
|
||||
Iterator citer = key.getColumnIterator();
|
||||
Iterator cItr = key.getColumnIterator();
|
||||
for ( int k = 0; k < idColumnSpan; k++ ) {
|
||||
Column column = (Column) citer.next();
|
||||
Column column = (Column) cItr.next();
|
||||
keyCols[k] = column.getQuotedName( factory.getDialect() );
|
||||
keyColReaders[k] = column.getReadExpr( factory.getDialect() );
|
||||
keyColReaderTemplates[k] = column.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() );
|
||||
|
@ -233,26 +233,21 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
cascadeDeletes.add( key.isCascadeDeleteEnabled() && factory.getDialect().supportsCascadeDelete() );
|
||||
}
|
||||
|
||||
//Span of the tables directly mapped by this entity and super-classes, if any
|
||||
coreTableSpan = tables.size();
|
||||
//Span of the tableNames directly mapped by this entity and super-classes, if any
|
||||
coreTableSpan = tableNames.size();
|
||||
|
||||
isNullableTable = new boolean[persistentClass.getJoinClosureSpan()];
|
||||
|
||||
int tableIndex = 0;
|
||||
Iterator joinIter = persistentClass.getJoinClosureIterator();
|
||||
while ( joinIter.hasNext() ) {
|
||||
Join join = (Join) joinIter.next();
|
||||
Iterator joinItr = persistentClass.getJoinClosureIterator();
|
||||
while ( joinItr.hasNext() ) {
|
||||
Join join = (Join) joinItr.next();
|
||||
|
||||
isNullableTable[tableIndex++] = join.isOptional();
|
||||
|
||||
Table table = join.getTable();
|
||||
|
||||
String tableName = table.getQualifiedName(
|
||||
factory.getDialect(),
|
||||
factory.getSettings().getDefaultCatalogName(),
|
||||
factory.getSettings().getDefaultSchemaName()
|
||||
);
|
||||
tables.add( tableName );
|
||||
final String tableName = determineTableName( table, jdbcEnvironment );
|
||||
tableNames.add( tableName );
|
||||
|
||||
KeyValue key = join.getKey();
|
||||
int joinIdColumnSpan = key.getColumnSpan();
|
||||
|
@ -261,10 +256,10 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
String[] keyColReaders = new String[joinIdColumnSpan];
|
||||
String[] keyColReaderTemplates = new String[joinIdColumnSpan];
|
||||
|
||||
Iterator citer = key.getColumnIterator();
|
||||
Iterator cItr = key.getColumnIterator();
|
||||
|
||||
for ( int k = 0; k < joinIdColumnSpan; k++ ) {
|
||||
Column column = (Column) citer.next();
|
||||
Column column = (Column) cItr.next();
|
||||
keyCols[k] = column.getQuotedName( factory.getDialect() );
|
||||
keyColReaders[k] = column.getReadExpr( factory.getDialect() );
|
||||
keyColReaderTemplates[k] = column.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() );
|
||||
|
@ -275,64 +270,55 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
cascadeDeletes.add( key.isCascadeDeleteEnabled() && factory.getDialect().supportsCascadeDelete() );
|
||||
}
|
||||
|
||||
naturalOrderTableNames = ArrayHelper.toStringArray( tables );
|
||||
naturalOrderTableNames = ArrayHelper.toStringArray( tableNames );
|
||||
naturalOrderTableKeyColumns = ArrayHelper.to2DStringArray( keyColumns );
|
||||
naturalOrderTableKeyColumnReaders = ArrayHelper.to2DStringArray( keyColumnReaders );
|
||||
naturalOrderTableKeyColumnReaderTemplates = ArrayHelper.to2DStringArray( keyColumnReaderTemplates );
|
||||
naturalOrderCascadeDeleteEnabled = ArrayHelper.toBooleanArray( cascadeDeletes );
|
||||
|
||||
ArrayList subtables = new ArrayList();
|
||||
ArrayList isConcretes = new ArrayList();
|
||||
ArrayList isDeferreds = new ArrayList();
|
||||
ArrayList isLazies = new ArrayList();
|
||||
ArrayList<String> subclassTableNames = new ArrayList<String>();
|
||||
ArrayList<Boolean> isConcretes = new ArrayList<Boolean>();
|
||||
ArrayList<Boolean> isDeferreds = new ArrayList<Boolean>();
|
||||
ArrayList<Boolean> isLazies = new ArrayList<Boolean>();
|
||||
|
||||
keyColumns = new ArrayList();
|
||||
titer = persistentClass.getSubclassTableClosureIterator();
|
||||
while ( titer.hasNext() ) {
|
||||
Table tab = (Table) titer.next();
|
||||
keyColumns = new ArrayList<String[]>();
|
||||
tItr = persistentClass.getSubclassTableClosureIterator();
|
||||
while ( tItr.hasNext() ) {
|
||||
Table tab = (Table) tItr.next();
|
||||
isConcretes.add( persistentClass.isClassOrSuperclassTable( tab ) );
|
||||
isDeferreds.add( Boolean.FALSE );
|
||||
isLazies.add( Boolean.FALSE );
|
||||
String tabname = tab.getQualifiedName(
|
||||
factory.getDialect(),
|
||||
factory.getSettings().getDefaultCatalogName(),
|
||||
factory.getSettings().getDefaultSchemaName()
|
||||
);
|
||||
subtables.add( tabname );
|
||||
final String tableName = determineTableName( tab, jdbcEnvironment );
|
||||
subclassTableNames.add( tableName );
|
||||
String[] key = new String[idColumnSpan];
|
||||
Iterator citer = tab.getPrimaryKey().getColumnIterator();
|
||||
Iterator cItr = tab.getPrimaryKey().getColumnIterator();
|
||||
for ( int k = 0; k < idColumnSpan; k++ ) {
|
||||
key[k] = ( (Column) citer.next() ).getQuotedName( factory.getDialect() );
|
||||
key[k] = ( (Column) cItr.next() ).getQuotedName( factory.getDialect() );
|
||||
}
|
||||
keyColumns.add( key );
|
||||
}
|
||||
|
||||
//Add joins
|
||||
joinIter = persistentClass.getSubclassJoinClosureIterator();
|
||||
while ( joinIter.hasNext() ) {
|
||||
Join join = (Join) joinIter.next();
|
||||
joinItr = persistentClass.getSubclassJoinClosureIterator();
|
||||
while ( joinItr.hasNext() ) {
|
||||
final Join join = (Join) joinItr.next();
|
||||
final Table joinTable = join.getTable();
|
||||
|
||||
Table tab = join.getTable();
|
||||
|
||||
isConcretes.add( persistentClass.isClassOrSuperclassTable( tab ) );
|
||||
isConcretes.add( persistentClass.isClassOrSuperclassTable( joinTable ) );
|
||||
isDeferreds.add( join.isSequentialSelect() );
|
||||
isLazies.add( join.isLazy() );
|
||||
|
||||
String tabname = tab.getQualifiedName(
|
||||
factory.getDialect(),
|
||||
factory.getSettings().getDefaultCatalogName(),
|
||||
factory.getSettings().getDefaultSchemaName()
|
||||
);
|
||||
subtables.add( tabname );
|
||||
String joinTableName = determineTableName( joinTable, jdbcEnvironment );
|
||||
subclassTableNames.add( joinTableName );
|
||||
String[] key = new String[idColumnSpan];
|
||||
Iterator citer = tab.getPrimaryKey().getColumnIterator();
|
||||
Iterator citer = joinTable.getPrimaryKey().getColumnIterator();
|
||||
for ( int k = 0; k < idColumnSpan; k++ ) {
|
||||
key[k] = ( (Column) citer.next() ).getQuotedName( factory.getDialect() );
|
||||
}
|
||||
keyColumns.add( key );
|
||||
}
|
||||
|
||||
String[] naturalOrderSubclassTableNameClosure = ArrayHelper.toStringArray( subtables );
|
||||
String[] naturalOrderSubclassTableNameClosure = ArrayHelper.toStringArray( subclassTableNames );
|
||||
String[][] naturalOrderSubclassTableKeyColumnClosure = ArrayHelper.to2DStringArray( keyColumns );
|
||||
isClassOrSuperclassTable = ArrayHelper.toBooleanArray( isConcretes );
|
||||
subclassTableSequentialSelect = ArrayHelper.toBooleanArray( isDeferreds );
|
||||
|
@ -347,9 +333,9 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
}
|
||||
|
||||
/**
|
||||
* Suppose an entity Client extends Person, mapped to the tables CLIENT and PERSON respectively.
|
||||
* Suppose an entity Client extends Person, mapped to the tableNames CLIENT and PERSON respectively.
|
||||
* For the Client entity:
|
||||
* naturalOrderTableNames -> PERSON, CLIENT; this reflects the sequence in which the tables are
|
||||
* naturalOrderTableNames -> PERSON, CLIENT; this reflects the sequence in which the tableNames are
|
||||
* added to the meta-data when the annotated entities are processed.
|
||||
* However, in some instances, for example when generating joins, the CLIENT table needs to be
|
||||
* the first table as it will the driving table.
|
||||
|
@ -357,7 +343,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
*/
|
||||
|
||||
tableSpan = naturalOrderTableNames.length;
|
||||
tableNames = reverse( naturalOrderTableNames, coreTableSpan );
|
||||
this.tableNames = reverse( naturalOrderTableNames, coreTableSpan );
|
||||
tableKeyColumns = reverse( naturalOrderTableKeyColumns, coreTableSpan );
|
||||
tableKeyColumnReaders = reverse( naturalOrderTableKeyColumnReaders, coreTableSpan );
|
||||
tableKeyColumnReaderTemplates = reverse( naturalOrderTableKeyColumnReaderTemplates, coreTableSpan );
|
||||
|
@ -365,7 +351,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
subclassTableKeyColumnClosure = reverse( naturalOrderSubclassTableKeyColumnClosure, coreTableSpan );
|
||||
|
||||
spaces = ArrayHelper.join(
|
||||
tableNames,
|
||||
this.tableNames,
|
||||
ArrayHelper.toStringArray( persistentClass.getSynchronizedTables() )
|
||||
);
|
||||
|
||||
|
@ -408,10 +394,10 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
throw new AssertionFailure( "Tablespan does not match height of joined-subclass hiearchy." );
|
||||
}
|
||||
|
||||
joinIter = persistentClass.getJoinClosureIterator();
|
||||
joinItr = persistentClass.getJoinClosureIterator();
|
||||
int j = coreTableSpan;
|
||||
while ( joinIter.hasNext() ) {
|
||||
Join join = (Join) joinIter.next();
|
||||
while ( joinItr.hasNext() ) {
|
||||
Join join = (Join) joinItr.next();
|
||||
|
||||
customSQLInsert[j] = join.getCustomSQLInsert();
|
||||
insertCallable[j] = customSQLInsert[j] != null && join.isCustomInsertCallable();
|
||||
|
@ -444,7 +430,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
factory.getSettings().getDefaultCatalogName(),
|
||||
factory.getSettings().getDefaultSchemaName()
|
||||
);
|
||||
propertyTableNumbers[i] = getTableId( tabname, tableNames );
|
||||
propertyTableNumbers[i] = getTableId( tabname, this.tableNames );
|
||||
naturalOrderPropertyTableNumbers[i] = getTableId( tabname, naturalOrderTableNames );
|
||||
i++;
|
||||
}
|
||||
|
|
|
@ -17,8 +17,10 @@ import java.util.Set;
|
|||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.DynamicFilterAliasGenerator;
|
||||
|
@ -123,6 +125,9 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
final SessionFactoryImplementor factory = creationContext.getSessionFactory();
|
||||
|
||||
final Database database = creationContext.getMetadata().getDatabase();
|
||||
final JdbcEnvironment jdbcEnvironment = database.getJdbcEnvironment();
|
||||
|
||||
// CLASS + TABLE
|
||||
|
||||
joinSpan = persistentClass.getJoinClosureSpan() + 1;
|
||||
|
@ -131,11 +136,8 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
isNullableTable = new boolean[joinSpan];
|
||||
keyColumnNames = new String[joinSpan][];
|
||||
final Table table = persistentClass.getRootTable();
|
||||
qualifiedTableNames[0] = table.getQualifiedName(
|
||||
factory.getDialect(),
|
||||
factory.getSettings().getDefaultCatalogName(),
|
||||
factory.getSettings().getDefaultSchemaName()
|
||||
);
|
||||
qualifiedTableNames[0] = determineTableName( table, jdbcEnvironment );
|
||||
|
||||
isInverseTable[0] = false;
|
||||
isNullableTable[0] = false;
|
||||
keyColumnNames[0] = getIdentifierColumnNames();
|
||||
|
@ -174,11 +176,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
int j = 1;
|
||||
while ( joinIter.hasNext() ) {
|
||||
Join join = (Join) joinIter.next();
|
||||
qualifiedTableNames[j] = join.getTable().getQualifiedName(
|
||||
factory.getDialect(),
|
||||
factory.getSettings().getDefaultCatalogName(),
|
||||
factory.getSettings().getDefaultSchemaName()
|
||||
);
|
||||
qualifiedTableNames[j] = determineTableName( join.getTable(), jdbcEnvironment );
|
||||
isInverseTable[j] = join.isInverse();
|
||||
isNullableTable[j] = join.isOptional();
|
||||
cascadeDeleteEnabled[j] = join.getKey().isCascadeDeleteEnabled() &&
|
||||
|
|
|
@ -19,10 +19,12 @@ import org.hibernate.AssertionFailure;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
|
||||
import org.hibernate.cfg.Settings;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -74,8 +76,6 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
super( persistentClass, cacheAccessStrategy, naturalIdRegionAccessStrategy, creationContext );
|
||||
|
||||
final SessionFactoryImplementor factory = creationContext.getSessionFactory();
|
||||
|
||||
if ( getIdentifierGenerator() instanceof IdentityGenerator ) {
|
||||
throw new MappingException(
|
||||
"Cannot use identity column key generation with <union-subclass> mapping for: " +
|
||||
|
@ -83,18 +83,13 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
|||
);
|
||||
}
|
||||
|
||||
final SessionFactoryImplementor factory = creationContext.getSessionFactory();
|
||||
final Database database = creationContext.getMetadata().getDatabase();
|
||||
final JdbcEnvironment jdbcEnvironment = database.getJdbcEnvironment();
|
||||
|
||||
// TABLE
|
||||
|
||||
tableName = persistentClass.getTable().getQualifiedName(
|
||||
factory.getDialect(),
|
||||
factory.getSettings().getDefaultCatalogName(),
|
||||
factory.getSettings().getDefaultSchemaName()
|
||||
);
|
||||
/*rootTableName = persistentClass.getRootTable().getQualifiedName(
|
||||
factory.getDialect(),
|
||||
factory.getDefaultCatalog(),
|
||||
factory.getDefaultSchema()
|
||||
);*/
|
||||
tableName = determineTableName( persistentClass.getTable(), jdbcEnvironment );
|
||||
|
||||
//Custom SQL
|
||||
|
||||
|
@ -173,14 +168,8 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
|||
HashSet subclassTables = new HashSet();
|
||||
iter = persistentClass.getSubclassTableClosureIterator();
|
||||
while ( iter.hasNext() ) {
|
||||
Table table = (Table) iter.next();
|
||||
subclassTables.add(
|
||||
table.getQualifiedName(
|
||||
factory.getDialect(),
|
||||
factory.getSettings().getDefaultCatalogName(),
|
||||
factory.getSettings().getDefaultSchemaName()
|
||||
)
|
||||
);
|
||||
final Table table = (Table) iter.next();
|
||||
subclassTables.add( determineTableName( table, jdbcEnvironment ) );
|
||||
}
|
||||
subclassSpaces = ArrayHelper.toStringArray( subclassTables );
|
||||
|
||||
|
@ -198,11 +187,7 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
|||
while ( iter.hasNext() ) {
|
||||
Table tab = (Table) iter.next();
|
||||
if ( !tab.isAbstractUnionTable() ) {
|
||||
String tableName = tab.getQualifiedName(
|
||||
factory.getDialect(),
|
||||
factory.getSettings().getDefaultCatalogName(),
|
||||
factory.getSettings().getDefaultSchemaName()
|
||||
);
|
||||
final String tableName = determineTableName( tab, jdbcEnvironment );
|
||||
tableNames.add( tableName );
|
||||
String[] key = new String[idColumnSpan];
|
||||
Iterator citer = tab.getPrimaryKey().getColumnIterator();
|
||||
|
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.test.boot.database.qualfiedTableNaming;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class JdbcMocks {
|
||||
|
||||
public static Connection createConnection(String databaseName, int majorVersion) {
|
||||
return createConnection( databaseName, majorVersion, -9999 );
|
||||
}
|
||||
|
||||
public static Connection createConnection(String databaseName, int majorVersion, int minorVersion) {
|
||||
DatabaseMetaDataHandler metadataHandler = new DatabaseMetaDataHandler( databaseName, majorVersion, minorVersion );
|
||||
ConnectionHandler connectionHandler = new ConnectionHandler();
|
||||
|
||||
DatabaseMetaData metadataProxy = ( DatabaseMetaData ) Proxy.newProxyInstance(
|
||||
ClassLoader.getSystemClassLoader(),
|
||||
new Class[] {DatabaseMetaData.class},
|
||||
metadataHandler
|
||||
);
|
||||
|
||||
Connection connectionProxy = ( Connection ) Proxy.newProxyInstance(
|
||||
ClassLoader.getSystemClassLoader(),
|
||||
new Class[] { Connection.class },
|
||||
connectionHandler
|
||||
);
|
||||
|
||||
metadataHandler.setConnectionProxy( connectionProxy );
|
||||
connectionHandler.setMetadataProxy( metadataProxy );
|
||||
|
||||
return connectionProxy;
|
||||
}
|
||||
|
||||
private static class ConnectionHandler implements InvocationHandler {
|
||||
private DatabaseMetaData metadataProxy;
|
||||
|
||||
public void setMetadataProxy(DatabaseMetaData metadataProxy) {
|
||||
this.metadataProxy = metadataProxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
final String methodName = method.getName();
|
||||
if ( "getMetaData".equals( methodName ) ) {
|
||||
return metadataProxy;
|
||||
}
|
||||
|
||||
if ( "toString".equals( methodName ) ) {
|
||||
return "Connection proxy [@" + hashCode() + "]";
|
||||
}
|
||||
|
||||
if ( "hashCode".equals( methodName ) ) {
|
||||
return Integer.valueOf( this.hashCode() );
|
||||
}
|
||||
|
||||
if ( "getCatalog".equals( methodName ) ) {
|
||||
return "DB1";
|
||||
}
|
||||
|
||||
if ( "supportsRefCursors".equals( methodName ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( canThrowSQLException( method ) ) {
|
||||
throw new SQLException();
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class DatabaseMetaDataHandler implements InvocationHandler {
|
||||
private final String databaseName;
|
||||
private final int majorVersion;
|
||||
private final int minorVersion;
|
||||
|
||||
private Connection connectionProxy;
|
||||
|
||||
public void setConnectionProxy(Connection connectionProxy) {
|
||||
this.connectionProxy = connectionProxy;
|
||||
}
|
||||
|
||||
private DatabaseMetaDataHandler(String databaseName, int majorVersion) {
|
||||
this( databaseName, majorVersion, -9999 );
|
||||
}
|
||||
|
||||
private DatabaseMetaDataHandler(String databaseName, int majorVersion, int minorVersion) {
|
||||
this.databaseName = databaseName;
|
||||
this.majorVersion = majorVersion;
|
||||
this.minorVersion = minorVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
final String methodName = method.getName();
|
||||
if ( "getDatabaseProductName".equals( methodName ) ) {
|
||||
return databaseName;
|
||||
}
|
||||
|
||||
if ( "getDatabaseMajorVersion".equals( methodName ) ) {
|
||||
return Integer.valueOf( majorVersion );
|
||||
}
|
||||
|
||||
if ( "getDatabaseMinorVersion".equals( methodName ) ) {
|
||||
return Integer.valueOf( minorVersion );
|
||||
}
|
||||
|
||||
if ( "getConnection".equals( methodName ) ) {
|
||||
return connectionProxy;
|
||||
}
|
||||
|
||||
if ( "toString".equals( methodName ) ) {
|
||||
return "DatabaseMetaData proxy [db-name=" + databaseName + ", version=" + majorVersion + "]";
|
||||
}
|
||||
|
||||
if ( "hashCode".equals( methodName ) ) {
|
||||
return Integer.valueOf( this.hashCode() );
|
||||
}
|
||||
|
||||
if ( "supportsNamedParameters".equals( methodName ) ) {
|
||||
return true ;
|
||||
}
|
||||
|
||||
if ( "supportsResultSetType".equals( methodName ) ) {
|
||||
return true ;
|
||||
}
|
||||
|
||||
if ( "supportsGetGeneratedKeys".equals( methodName ) ) {
|
||||
return true ;
|
||||
}
|
||||
|
||||
if ( "supportsBatchUpdates".equals( methodName ) ) {
|
||||
return true ;
|
||||
}
|
||||
|
||||
if ( "dataDefinitionIgnoredInTransactions".equals( methodName ) ) {
|
||||
return false ;
|
||||
}
|
||||
|
||||
if ( "dataDefinitionCausesTransactionCommit".equals( methodName ) ) {
|
||||
return false ;
|
||||
}
|
||||
|
||||
if ( "getSQLKeywords".equals( methodName ) ) {
|
||||
return "after,ansi,append,attach,audit,before,bitmap,boolean,buffered,byte,cache,call,cluster,clustersize,codeset,database,datafiles,dataskip,datetime,dba,dbdate,dbmoney,debug,define,delimiter,deluxe,detach,dirty,distributions,document,each,elif,exclusive,exit,explain,express,expression,extend,extent,file,fillfactor,foreach,format,fraction,fragment,gk,hash,high,hold,hybrid,if,index,init,labeleq,labelge,labelgt,labelle,labellt,let,listing,lock,log,low,matches,maxerrors,medium,mode,modify,money,mounting,new,nvarchar,off,old,operational,optical,optimization,page,pdqpriority,pload,private,raise,range,raw,recordend,recover,referencing,rejectfile,release,remainder,rename,reserve,resolution,resource,resume,return,returning,returns,ridlist,robin,rollforward,round,row,rowids,sameas,samples,schedule,scratch,serial,share,skall,skinhibit,skshow,smallfloat,stability,standard,start,static,statistics,stdev,step,sync,synonym,system,temp,text,timeout,trace,trigger,units,unlock,variance,wait,while,xload,xunload" ;
|
||||
}
|
||||
|
||||
if ( "getSQLStateType".equals( methodName ) ) {
|
||||
return DatabaseMetaData.sqlStateXOpen ;
|
||||
}
|
||||
|
||||
if ( "locatorsUpdateCopy".equals( methodName ) ) {
|
||||
return false ;
|
||||
}
|
||||
|
||||
if ( "getTypeInfo".equals( methodName ) ) {
|
||||
com.sun.rowset.CachedRowSetImpl rowSet = new com.sun.rowset.CachedRowSetImpl();
|
||||
return rowSet ;
|
||||
}
|
||||
|
||||
if ( "storesLowerCaseIdentifiers".equals( methodName ) ) {
|
||||
return true ;
|
||||
}
|
||||
|
||||
if ( "storesUpperCaseIdentifiers".equals( methodName ) ) {
|
||||
return false ;
|
||||
}
|
||||
|
||||
if ( "getCatalogSeparator".equals( methodName ) ) {
|
||||
return ":" ;
|
||||
}
|
||||
|
||||
if ( "isCatalogAtStart".equals( methodName ) ) {
|
||||
return true ;
|
||||
}
|
||||
|
||||
if ( canThrowSQLException( method ) ) {
|
||||
throw new SQLException();
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean canThrowSQLException(Method method) {
|
||||
final Class[] exceptions = method.getExceptionTypes();
|
||||
for ( Class exceptionType : exceptions ) {
|
||||
if ( SQLException.class.isAssignableFrom( exceptionType ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.test.boot.database.qualfiedTableNaming;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.boot.model.relational.Namespace;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.engine.jdbc.env.spi.NameQualifierSupport;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.SingleTableEntityPersister;
|
||||
import org.hibernate.tool.schema.internal.StandardTableExporter;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class QualifiedTableNamingTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { Box.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createSchema() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addSettings(Map settings) {
|
||||
super.addSettings( settings );
|
||||
settings.put( AvailableSettings.DIALECT, TestDialect.class );
|
||||
settings.put( AvailableSettings.CONNECTION_PROVIDER, MockedConnectionProvider.class.getName() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQualifiedNameSeparator() throws Exception {
|
||||
Namespace.Name namespaceName = new Namespace.Name(
|
||||
Identifier.toIdentifier( "DB1" ),
|
||||
Identifier.toIdentifier( "PUBLIC" )
|
||||
);
|
||||
|
||||
String expectedName = null;
|
||||
|
||||
for ( Namespace namespace : metadata().getDatabase().getNamespaces() ) {
|
||||
if ( !namespace.getName().equals( namespaceName ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
assertEquals( 1, namespace.getTables().size() );
|
||||
|
||||
expectedName = metadata().getDatabase().getJdbcEnvironment().getQualifiedObjectNameFormatter().format(
|
||||
namespace.getTables().iterator().next().getQualifiedTableName(),
|
||||
getDialect()
|
||||
);
|
||||
}
|
||||
|
||||
assertNotNull( expectedName );
|
||||
|
||||
SingleTableEntityPersister persister = (SingleTableEntityPersister) sessionFactory().getEntityPersister( Box.class.getName() );
|
||||
assertEquals( expectedName, persister.getTableName() );
|
||||
}
|
||||
|
||||
@Entity(name = "Box")
|
||||
@javax.persistence.Table(name = "Box", schema = "PUBLIC", catalog = "DB1")
|
||||
public static class Box {
|
||||
@Id
|
||||
public Integer id;
|
||||
public String value;
|
||||
}
|
||||
|
||||
public static class TestDialect extends Dialect {
|
||||
@Override
|
||||
public NameQualifierSupport getNameQualifierSupport() {
|
||||
return NameQualifierSupport.BOTH;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MockedConnectionProvider implements ConnectionProvider {
|
||||
private Connection connection;
|
||||
|
||||
@Override
|
||||
public Connection getConnection() throws SQLException {
|
||||
if (connection == null) {
|
||||
connection = JdbcMocks.createConnection( "db1", 0 );
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeConnection(Connection conn) throws SQLException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsAggressiveRelease() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isUnwrappableAs(Class unwrapType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T unwrap(Class<T> unwrapType) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue