diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/relational/QualifiedName.java b/hibernate-core/src/main/java/org/hibernate/boot/model/relational/QualifiedName.java
index 7246d86e11..accffef431 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/relational/QualifiedName.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/relational/QualifiedName.java
@@ -14,6 +14,11 @@ import org.hibernate.boot.model.naming.Identifier;
*
{@link java.sql.DatabaseMetaData#isCatalogAtStart}
* {@link java.sql.DatabaseMetaData#getCatalogSeparator()}
*
+ *
+ * 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.
+ *
+ * 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();
}
diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Table.java b/hibernate-core/src/main/java/org/hibernate/mapping/Table.java
index 77da722fda..92bd8623ff 100644
--- a/hibernate-core/src/main/java/org/hibernate/mapping/Table.java
+++ b/hibernate-core/src/main/java/org/hibernate/mapping/Table.java
@@ -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 ) {
diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java
index 424154a1e1..61631bb958 100644
--- a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java
+++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java
@@ -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) {
diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
index 05f969ce3a..ecfe0cff93 100644
--- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
+++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
@@ -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;
diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java
index 377586908b..4c8f96b770 100644
--- a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java
+++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java
@@ -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 tableNames = new ArrayList();
+ ArrayList keyColumns = new ArrayList();
+ ArrayList keyColumnReaders = new ArrayList();
+ ArrayList keyColumnReaderTemplates = new ArrayList();
+ ArrayList cascadeDeletes = new ArrayList();
+ 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 subclassTableNames = new ArrayList();
+ ArrayList isConcretes = new ArrayList();
+ ArrayList isDeferreds = new ArrayList();
+ ArrayList isLazies = new ArrayList();
- keyColumns = new ArrayList();
- titer = persistentClass.getSubclassTableClosureIterator();
- while ( titer.hasNext() ) {
- Table tab = (Table) titer.next();
+ keyColumns = new ArrayList();
+ 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++;
}
diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java
index 66d3341f25..85db93a138 100644
--- a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java
+++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java
@@ -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() &&
diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java
index 4146f6d784..47c6912af2 100644
--- a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java
+++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java
@@ -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 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();
diff --git a/hibernate-core/src/test/java/org/hibernate/test/boot/database/qualfiedTableNaming/JdbcMocks.java b/hibernate-core/src/test/java/org/hibernate/test/boot/database/qualfiedTableNaming/JdbcMocks.java
new file mode 100644
index 0000000000..54d9a801c1
--- /dev/null
+++ b/hibernate-core/src/test/java/org/hibernate/test/boot/database/qualfiedTableNaming/JdbcMocks.java
@@ -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 .
+ */
+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;
+ }
+}
diff --git a/hibernate-core/src/test/java/org/hibernate/test/boot/database/qualfiedTableNaming/QualifiedTableNamingTest.java b/hibernate-core/src/test/java/org/hibernate/test/boot/database/qualfiedTableNaming/QualifiedTableNamingTest.java
new file mode 100644
index 0000000000..c02271213d
--- /dev/null
+++ b/hibernate-core/src/test/java/org/hibernate/test/boot/database/qualfiedTableNaming/QualifiedTableNamingTest.java
@@ -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 .
+ */
+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 unwrap(Class unwrapType) {
+ return null;
+ }
+ }
+
+}