HHH-3439 : Mappings

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@15210 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Steve Ebersole 2008-09-17 16:44:23 +00:00
parent 3a23f9d1b8
commit aa7f7a7822
3 changed files with 956 additions and 532 deletions

View File

@ -66,11 +66,15 @@ import org.hibernate.MappingException;
import org.hibernate.MappingNotFoundException;
import org.hibernate.SessionFactory;
import org.hibernate.SessionFactoryObserver;
import org.hibernate.DuplicateMappingException;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.engine.FilterDefinition;
import org.hibernate.engine.Mapping;
import org.hibernate.engine.NamedQueryDefinition;
import org.hibernate.engine.NamedSQLQueryDefinition;
import org.hibernate.engine.ResultSetMappingDefinition;
import org.hibernate.event.AutoFlushEventListener;
import org.hibernate.event.DeleteEventListener;
import org.hibernate.event.DirtyCheckEventListener;
@ -115,6 +119,9 @@ import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.Table;
import org.hibernate.mapping.UniqueKey;
import org.hibernate.mapping.FetchProfile;
import org.hibernate.mapping.DenormalizedTable;
import org.hibernate.mapping.TypeDef;
import org.hibernate.mapping.Column;
import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.secure.JACCConfiguration;
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
@ -156,68 +163,73 @@ public class Configuration implements Serializable {
protected Map collections;
protected Map tables;
protected List auxiliaryDatabaseObjects;
protected Map sqlFunctions;
protected Map namedQueries;
protected Map namedSqlQueries;
/**
* Map<String, SqlResultSetMapping> result set name, result set description
*/
protected Map sqlResultSetMappings;
protected Map/*<String, SqlResultSetMapping>*/ sqlResultSetMappings;
protected Map typeDefs;
protected Map filterDefinitions;
protected Map fetchProfiles;
protected Map tableNameBinding;
protected Map columnNameBindingPerTable;
protected List secondPasses;
protected List propertyReferences;
// protected List extendsQueue;
protected Map extendsQueue;
protected Map tableNameBinding;
protected Map columnNameBindingPerTable;
protected Map sqlFunctions;
private Interceptor interceptor;
private Properties properties;
private EntityResolver entityResolver;
private EntityNotFoundDelegate entityNotFoundDelegate;
protected transient XMLHelper xmlHelper;
protected transient Map typeDefs;
protected NamingStrategy namingStrategy;
private SessionFactoryObserver sessionFactoryObserver;
private EventListeners eventListeners;
protected final SettingsFactory settingsFactory;
private SessionFactoryObserver sessionFactoryObserver;
private transient Mapping mapping = buildMapping();
protected void reset() {
classes = new HashMap();
imports = new HashMap();
collections = new HashMap();
tables = new TreeMap();
namedQueries = new HashMap();
namedSqlQueries = new HashMap();
sqlResultSetMappings = new HashMap();
xmlHelper = new XMLHelper();
typeDefs = new HashMap();
filterDefinitions = new HashMap();
fetchProfiles = new HashMap();
auxiliaryDatabaseObjects = new ArrayList();
tableNameBinding = new HashMap();
columnNameBindingPerTable = new HashMap();
propertyReferences = new ArrayList();
secondPasses = new ArrayList();
// extendsQueue = new ArrayList();
extendsQueue = new HashMap();
namingStrategy = DefaultNamingStrategy.INSTANCE;
xmlHelper = new XMLHelper();
interceptor = EmptyInterceptor.INSTANCE;
properties = Environment.getProperties();
entityResolver = XMLHelper.DEFAULT_DTD_RESOLVER;
eventListeners = new EventListeners();
filterDefinitions = new HashMap();
fetchProfiles = new HashMap();
// extendsQueue = new ArrayList();
extendsQueue = new HashMap();
auxiliaryDatabaseObjects = new ArrayList();
tableNameBinding = new HashMap();
columnNameBindingPerTable = new HashMap();
namingStrategy = DefaultNamingStrategy.INSTANCE;
sqlFunctions = new HashMap();
}
private transient Mapping mapping = buildMapping();
protected Configuration(SettingsFactory settingsFactory) {
this.settingsFactory = settingsFactory;
reset();
@ -710,25 +722,7 @@ public class Configuration implements Serializable {
* mappings to.
*/
public Mappings createMappings() {
return new Mappings(
classes,
collections,
tables,
namedQueries,
namedSqlQueries,
sqlResultSetMappings,
imports,
secondPasses,
propertyReferences,
namingStrategy,
typeDefs,
filterDefinitions,
fetchProfiles,
extendsQueue,
auxiliaryDatabaseObjects,
tableNameBinding,
columnNameBindingPerTable
);
return new MappingsImpl();
}
@ -2185,8 +2179,8 @@ public class Configuration implements Serializable {
filterDefinitions.put( definition.getFilterName(), definition );
}
public Map getFetchProfiles() {
return fetchProfiles;
public Iterator iterateFetchProfiles() {
return fetchProfiles.values().iterator();
}
public void addFetchProfile(FetchProfile fetchProfile) {
@ -2212,4 +2206,494 @@ public class Configuration implements Serializable {
public void setSessionFactoryObserver(SessionFactoryObserver sessionFactoryObserver) {
this.sessionFactoryObserver = sessionFactoryObserver;
}
// Mappings impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Internal implementation of the Mappings interface giving access to the Configuration's internal
* <tt>metadata repository</tt> state ({@link Configuration#classes}, {@link Configuration#tables}, etc).
*/
protected class MappingsImpl implements Mappings, Serializable {
private String schemaName;
public String getSchemaName() {
return schemaName;
}
public void setSchemaName(String schemaName) {
this.schemaName = schemaName;
}
private String catalogName;
public String getCatalogName() {
return catalogName;
}
public void setCatalogName(String catalogName) {
this.catalogName = catalogName;
}
private String defaultPackage;
public String getDefaultPackage() {
return defaultPackage;
}
public void setDefaultPackage(String defaultPackage) {
this.defaultPackage = defaultPackage;
}
private boolean autoImport;
public boolean isAutoImport() {
return autoImport;
}
public void setAutoImport(boolean autoImport) {
this.autoImport = autoImport;
}
private boolean defaultLazy;
public boolean isDefaultLazy() {
return defaultLazy;
}
public void setDefaultLazy(boolean defaultLazy) {
this.defaultLazy = defaultLazy;
}
private String defaultCascade;
public String getDefaultCascade() {
return defaultCascade;
}
public void setDefaultCascade(String defaultCascade) {
this.defaultCascade = defaultCascade;
}
private String defaultAccess;
public String getDefaultAccess() {
return defaultAccess;
}
public void setDefaultAccess(String defaultAccess) {
this.defaultAccess = defaultAccess;
}
public NamingStrategy getNamingStrategy() {
return namingStrategy;
}
public void setNamingStrategy(NamingStrategy namingStrategy) {
Configuration.this.namingStrategy = namingStrategy;
}
public Iterator iterateClasses() {
return classes.values().iterator();
}
public PersistentClass getClass(String entityName) {
return ( PersistentClass ) classes.get( entityName );
}
public PersistentClass locatePersistentClassByEntityName(String entityName) {
PersistentClass persistentClass = ( PersistentClass ) classes.get( entityName );
if ( persistentClass == null ) {
String actualEntityName = ( String ) imports.get( entityName );
if ( StringHelper.isNotEmpty( actualEntityName ) ) {
persistentClass = ( PersistentClass ) classes.get( actualEntityName );
}
}
return persistentClass;
}
public void addClass(PersistentClass persistentClass) throws DuplicateMappingException {
Object old = classes.put( persistentClass.getEntityName(), persistentClass );
if ( old != null ) {
throw new DuplicateMappingException( "class/entity", persistentClass.getEntityName() );
}
}
public void addImport(String entityName, String rename) throws DuplicateMappingException {
String existing = ( String ) imports.put( rename, entityName );
if ( existing != null ) {
if ( existing.equals( entityName ) ) {
log.info( "duplicate import: {} -> {}", entityName, rename );
}
else {
throw new DuplicateMappingException(
"duplicate import: " + rename + " refers to both " + entityName +
" and " + existing + " (try using auto-import=\"false\")",
"import",
rename
);
}
}
}
public Collection getCollection(String role) {
return ( Collection ) collections.get( role );
}
public Iterator iterateCollections() {
return collections.values().iterator();
}
public void addCollection(Collection collection) throws DuplicateMappingException {
Object old = collections.put( collection.getRole(), collection );
if ( old != null ) {
throw new DuplicateMappingException( "collection role", collection.getRole() );
}
}
public Table getTable(String schema, String catalog, String name) {
String key = Table.qualify(catalog, schema, name);
return (Table) tables.get(key);
}
public Iterator iterateTables() {
return tables.values().iterator();
}
public Table addTable(
String schema,
String catalog,
String name,
String subselect,
boolean isAbstract) {
String key = subselect == null ? Table.qualify( catalog, schema, name ) : subselect;
Table table = ( Table ) tables.get( key );
if ( table == null ) {
table = new Table();
table.setAbstract( isAbstract );
table.setName( name );
table.setSchema( schema );
table.setCatalog( catalog );
table.setSubselect( subselect );
tables.put( key, table );
}
else {
if ( !isAbstract ) {
table.setAbstract( false );
}
}
return table;
}
public Table addDenormalizedTable(
String schema,
String catalog,
String name,
boolean isAbstract,
String subselect,
Table includedTable) throws DuplicateMappingException {
String key = subselect == null ? Table.qualify(catalog, schema, name) : subselect;
if ( tables.containsKey( key ) ) {
throw new DuplicateMappingException( "table", name );
}
Table table = new DenormalizedTable( includedTable );
table.setAbstract( isAbstract );
table.setName( name );
table.setSchema( schema );
table.setCatalog( catalog );
table.setSubselect( subselect );
tables.put( key, table );
return table;
}
public NamedQueryDefinition getQuery(String name) {
return ( NamedQueryDefinition ) namedQueries.get( name );
}
public void addQuery(String name, NamedQueryDefinition query) throws DuplicateMappingException {
checkQueryName( name );
namedQueries.put( name.intern(), query );
}
private void checkQueryName(String name) throws DuplicateMappingException {
if ( namedQueries.containsKey( name ) || namedSqlQueries.containsKey( name ) ) {
throw new DuplicateMappingException( "query", name );
}
}
public NamedSQLQueryDefinition getSQLQuery(String name) {
return ( NamedSQLQueryDefinition ) namedSqlQueries.get( name );
}
public void addSQLQuery(String name, NamedSQLQueryDefinition query) throws DuplicateMappingException {
checkQueryName( name );
namedSqlQueries.put( name.intern(), query );
}
public ResultSetMappingDefinition getResultSetMapping(String name) {
return (ResultSetMappingDefinition) sqlResultSetMappings.get(name);
}
public void addResultSetMapping(ResultSetMappingDefinition sqlResultSetMapping) throws DuplicateMappingException {
Object old = sqlResultSetMappings.put( sqlResultSetMapping.getName(), sqlResultSetMapping );
if ( old != null ) {
throw new DuplicateMappingException( "resultSet", sqlResultSetMapping.getName() );
}
}
public TypeDef getTypeDef(String typeName) {
return ( TypeDef ) typeDefs.get( typeName );
}
public void addTypeDef(String typeName, String typeClass, Properties paramMap) {
TypeDef def = new TypeDef( typeClass, paramMap );
typeDefs.put( typeName, def );
log.debug( "Added " + typeName + " with class " + typeClass );
}
public Map getFilterDefinitions() {
return filterDefinitions;
}
public FilterDefinition getFilterDefinition(String name) {
return ( FilterDefinition ) filterDefinitions.get( name );
}
public void addFilterDefinition(FilterDefinition definition) {
filterDefinitions.put( definition.getFilterName(), definition );
}
public FetchProfile findOrCreateFetchProfile(String name) {
FetchProfile profile = ( FetchProfile ) fetchProfiles.get( name );
if ( profile == null ) {
profile = new FetchProfile( name );
fetchProfiles.put( name, profile );
}
return profile;
}
public Iterator iterateAuxliaryDatabaseObjects() {
return auxiliaryDatabaseObjects.iterator();
}
public ListIterator iterateAuxliaryDatabaseObjectsInReverse() {
return auxiliaryDatabaseObjects.listIterator( auxiliaryDatabaseObjects.size() );
}
public void addAuxiliaryDatabaseObject(AuxiliaryDatabaseObject auxiliaryDatabaseObject) {
auxiliaryDatabaseObjects.add( auxiliaryDatabaseObject );
}
/**
* Internal struct used to help track physical table names to logical table names.
*/
private class TableDescription implements Serializable {
final String logicalName;
final Table denormalizedSupertable;
TableDescription(String logicalName, Table denormalizedSupertable) {
this.logicalName = logicalName;
this.denormalizedSupertable = denormalizedSupertable;
}
}
public String getLogicalTableName(Table table) throws MappingException {
return getLogicalTableName( table.getQuotedSchema(), table.getCatalog(), table.getQuotedName() );
}
private String getLogicalTableName(String schema, String catalog, String physicalName) throws MappingException {
String key = buildTableNameKey( schema, catalog, physicalName );
TableDescription descriptor = (TableDescription) tableNameBinding.get( key );
if (descriptor == null) {
throw new MappingException( "Unable to find physical table: " + physicalName);
}
return descriptor.logicalName;
}
public void addTableBinding(
String schema,
String catalog,
String logicalName,
String physicalName,
Table denormalizedSuperTable) throws DuplicateMappingException {
String key = buildTableNameKey( schema, catalog, physicalName );
TableDescription tableDescription = new TableDescription( logicalName, denormalizedSuperTable );
TableDescription oldDescriptor = ( TableDescription ) tableNameBinding.put( key, tableDescription );
if ( oldDescriptor != null && ! oldDescriptor.logicalName.equals( logicalName ) ) {
//TODO possibly relax that
throw new DuplicateMappingException(
"Same physical table name [" + physicalName + "] references several logical table names: [" +
oldDescriptor.logicalName + "], [" + logicalName + ']',
"table",
physicalName
);
}
}
private String buildTableNameKey(String schema, String catalog, String finalName) {
StringBuffer keyBuilder = new StringBuffer();
if (schema != null) keyBuilder.append( schema );
keyBuilder.append( ".");
if (catalog != null) keyBuilder.append( catalog );
keyBuilder.append( ".");
keyBuilder.append( finalName );
return keyBuilder.toString();
}
/**
* Internal struct used to maintain xref between physical and logical column
* names for a table. Mainly this is used to ensure that the defined
* {@link NamingStrategy} is not creating duplicate column names.
*/
private class TableColumnNameBinding implements Serializable {
private final String tableName;
private Map/*<String, String>*/ logicalToPhysical = new HashMap();
private Map/*<String, String>*/ physicalToLogical = new HashMap();
private TableColumnNameBinding(String tableName) {
this.tableName = tableName;
}
public void addBinding(String logicalName, Column physicalColumn) {
bindLogicalToPhysical( logicalName, physicalColumn );
bindPhysicalToLogical( logicalName, physicalColumn );
}
private void bindLogicalToPhysical(String logicalName, Column physicalColumn) throws DuplicateMappingException {
final String logicalKey = logicalName.toLowerCase();
final String physicalName = physicalColumn.getQuotedName();
final String existingPhysicalName = ( String ) logicalToPhysical.put( logicalKey, physicalName );
if ( existingPhysicalName != null ) {
boolean areSamePhysicalColumn = physicalColumn.isQuoted()
? existingPhysicalName.equals( physicalName )
: existingPhysicalName.equalsIgnoreCase( physicalName );
if ( ! areSamePhysicalColumn ) {
throw new DuplicateMappingException(
" Table [" + tableName + "] contains logical column name [" + logicalName
+ "] referenced by multiple physical column names: [" + existingPhysicalName
+ "], [" + physicalName + "]",
"column-binding",
tableName + "." + logicalName
);
}
}
}
private void bindPhysicalToLogical(String logicalName, Column physicalColumn) throws DuplicateMappingException {
final String physicalName = physicalColumn.getQuotedName();
final String existingLogicalName = ( String ) physicalToLogical.put( physicalName, logicalName );
if ( existingLogicalName != null && ! existingLogicalName.equals( logicalName ) ) {
throw new DuplicateMappingException(
" Table [" + tableName + "] contains phyical column name [" + physicalName
+ "] represented by different logical column names: [" + existingLogicalName
+ "], [" + logicalName + "]",
"column-binding",
tableName + "." + physicalName
);
}
}
}
public void addColumnBinding(String logicalName, Column physicalColumn, Table table) throws DuplicateMappingException {
TableColumnNameBinding binding = ( TableColumnNameBinding ) columnNameBindingPerTable.get( table );
if ( binding == null ) {
binding = new TableColumnNameBinding( table.getName() );
columnNameBindingPerTable.put( table, binding );
}
binding.addBinding( logicalName, physicalColumn );
}
public String getPhysicalColumnName(String logicalName, Table table) throws MappingException {
logicalName = logicalName.toLowerCase();
String finalName = null;
Table currentTable = table;
do {
TableColumnNameBinding binding = ( TableColumnNameBinding ) columnNameBindingPerTable.get( currentTable );
if ( binding != null ) {
finalName = ( String ) binding.logicalToPhysical.get( logicalName );
}
String key = buildTableNameKey(
currentTable.getSchema(), currentTable.getCatalog(), currentTable.getName()
);
TableDescription description = ( TableDescription ) tableNameBinding.get( key );
if ( description != null ) {
currentTable = description.denormalizedSupertable;
}
} while ( finalName == null && currentTable != null );
if ( finalName == null ) {
throw new MappingException(
"Unable to find column with logical name " + logicalName + " in table " + table.getName()
);
}
return finalName;
}
public String getLogicalColumnName(String physicalName, Table table) throws MappingException {
String logical = null;
Table currentTable = table;
TableDescription description = null;
do {
TableColumnNameBinding binding = ( TableColumnNameBinding ) columnNameBindingPerTable.get( currentTable );
if ( binding != null ) {
logical = ( String ) binding.physicalToLogical.get( physicalName );
}
String key = buildTableNameKey(
currentTable.getSchema(), currentTable.getCatalog(), currentTable.getName()
);
description = ( TableDescription ) tableNameBinding.get( key );
if ( description != null ) {
currentTable = description.denormalizedSupertable;
}
}
while ( logical == null && currentTable != null && description != null );
if ( logical == null ) {
throw new MappingException(
"Unable to find logical column name from physical name "
+ physicalName + " in table " + table.getName()
);
}
return logical;
}
public void addSecondPass(SecondPass sp) {
addSecondPass( sp, false );
}
public void addSecondPass(SecondPass sp, boolean onTopOfTheQueue) {
if ( onTopOfTheQueue ) {
secondPasses.add( 0, sp );
}
else {
secondPasses.add( sp );
}
}
public void addPropertyReference(String referencedClass, String propertyName) {
propertyReferences.add( new PropertyReference( referencedClass, propertyName, false ) );
}
public void addUniquePropertyReference(String referencedClass, String propertyName) {
propertyReferences.add( new PropertyReference( referencedClass, propertyName, true ) );
}
public void addToExtendsQueue(ExtendsQueueEntry entry) {
extendsQueue.put( entry, null );
}
}
}

View File

@ -26,13 +26,10 @@ package org.hibernate.cfg;
import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.HashMap;
import java.util.Map;
import java.util.ListIterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.DuplicateMappingException;
import org.hibernate.MappingException;
import org.hibernate.engine.FilterDefinition;
@ -40,542 +37,485 @@ import org.hibernate.engine.NamedQueryDefinition;
import org.hibernate.engine.NamedSQLQueryDefinition;
import org.hibernate.engine.ResultSetMappingDefinition;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.DenormalizedTable;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Table;
import org.hibernate.mapping.TypeDef;
import org.hibernate.mapping.AuxiliaryDatabaseObject;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.FetchProfile;
import org.hibernate.util.StringHelper;
/**
* A collection of mappings from classes and collections to
* relational database tables. (Represents a single
* <tt>&lt;hibernate-mapping&gt;</tt> element.)
* A collection of mappings from classes and collections to relational database tables. Represents a single
* <tt>&lt;hibernate-mapping&gt;</tt> element.
* <p/>
* todo : the statement about this representing a single mapping element is simply not true if it was ever the case.
* this contract actually represents 3 scopes of information: <ol>
* <li><i>bounded</i> state : this is information which is indeed scoped by a single mapping</li>
* <li><i>unbounded</i> state : this is information which is Configuration wide (think of metadata repository)</li>
* <li><i>transient</i> state : state which changed at its own pace (naming strategy)</li>
* </ol>
*
* @author Gavin King
* @author Steve Ebersole
*/
public class Mappings implements Serializable {
private static final Logger log = LoggerFactory.getLogger(Mappings.class);
protected final Map classes;
protected final Map collections;
protected final Map tables;
protected final Map queries;
protected final Map sqlqueries;
protected final Map resultSetMappings;
protected final Map typeDefs;
protected final List secondPasses;
protected final Map imports;
protected String schemaName;
protected String catalogName;
protected String defaultCascade;
protected String defaultPackage;
protected String defaultAccess;
protected boolean autoImport;
protected boolean defaultLazy;
protected final List propertyReferences;
protected final NamingStrategy namingStrategy;
protected final Map filterDefinitions;
protected final Map fetchProfiles;
protected final List auxiliaryDatabaseObjects;
protected final Map extendsQueue;
// private final List extendsQueue;
public interface Mappings {
/**
* binding table between the logical column name and the name out of the naming strategy
* for each table.
* According that when the column name is not set, the property name is considered as such
* This means that while theorically possible through the naming strategy contract, it is
* forbidden to have 2 real columns having the same logical name
* <Table, ColumnNames >
* Get the current naming strategy.
*
* @return The current naming strategy.
*/
protected final Map columnNameBindingPerTable;
/**
* binding between logical table name and physical one (ie after the naming strategy has been applied)
* <String, TableDescription>
*/
protected final Map tableNameBinding;
Mappings(
final Map classes,
final Map collections,
final Map tables,
final Map queries,
final Map sqlqueries,
final Map sqlResultSetMappings,
final Map imports,
final List secondPasses,
final List propertyReferences,
final NamingStrategy namingStrategy,
final Map typeDefs,
final Map filterDefinitions,
final Map fetchProfiles,
// final List extendsQueue,
final Map extendsQueue,
final List auxiliaryDatabaseObjects,
final Map tableNamebinding,
final Map columnNameBindingPerTable) {
this.classes = classes;
this.collections = collections;
this.queries = queries;
this.sqlqueries = sqlqueries;
this.resultSetMappings = sqlResultSetMappings;
this.tables = tables;
this.imports = imports;
this.secondPasses = secondPasses;
this.propertyReferences = propertyReferences;
this.namingStrategy = namingStrategy;
this.typeDefs = typeDefs;
this.filterDefinitions = filterDefinitions;
this.fetchProfiles = fetchProfiles;
this.extendsQueue = extendsQueue;
this.auxiliaryDatabaseObjects = auxiliaryDatabaseObjects;
this.tableNameBinding = tableNamebinding;
this.columnNameBindingPerTable = columnNameBindingPerTable;
}
public void addClass(PersistentClass persistentClass) throws MappingException {
Object old = classes.put( persistentClass.getEntityName(), persistentClass );
if ( old!=null ) {
throw new DuplicateMappingException( "class/entity", persistentClass.getEntityName() );
}
}
public void addCollection(Collection collection) throws MappingException {
Object old = collections.put( collection.getRole(), collection );
if ( old!=null ) {
throw new DuplicateMappingException( "collection role", collection.getRole() );
}
}
public PersistentClass getClass(String className) {
return (PersistentClass) classes.get(className);
}
public Collection getCollection(String role) {
return (Collection) collections.get(role);
}
public void addImport(String className, String rename) throws MappingException {
String existing = (String) imports.put(rename, className);
if ( existing!=null ) {
if ( existing.equals(className) ) {
log.info( "duplicate import: " + className + "->" + rename );
}
else {
throw new DuplicateMappingException(
"duplicate import: " + rename +
" refers to both " + className +
" and " + existing +
" (try using auto-import=\"false\")",
"import",
rename
);
}
}
}
public Table addTable(String schema,
String catalog,
String name,
String subselect,
boolean isAbstract
) {
String key = subselect==null ?
Table.qualify(catalog, schema, name) :
subselect;
Table table = (Table) tables.get(key);
if (table == null) {
table = new Table();
table.setAbstract(isAbstract);
table.setName(name);
table.setSchema(schema);
table.setCatalog(catalog);
table.setSubselect(subselect);
tables.put(key, table);
}
else {
if (!isAbstract) table.setAbstract(false);
}
return table;
}
public Table addDenormalizedTable(
String schema,
String catalog,
String name,
boolean isAbstract,
String subselect,
Table includedTable)
throws MappingException {
String key = subselect==null ?
Table.qualify(catalog, schema, name) :
subselect;
if ( tables.containsKey(key) ) {
throw new DuplicateMappingException("table", name);
}
Table table = new DenormalizedTable(includedTable);
table.setAbstract(isAbstract);
table.setName(name);
table.setSchema(schema);
table.setCatalog(catalog);
table.setSubselect(subselect);
tables.put(key, table);
return table;
}
public Table getTable(String schema, String catalog, String name) {
String key = Table.qualify(catalog, schema, name);
return (Table) tables.get(key);
}
public String getSchemaName() {
return schemaName;
}
public String getCatalogName() {
return catalogName;
}
public String getDefaultCascade() {
return defaultCascade;
}
public NamingStrategy getNamingStrategy();
/**
* Sets the schemaName.
* @param schemaName The schemaName to set
* Set the current naming strategy.
*
* @param namingStrategy The naming strategy to use.
*/
public void setSchemaName(String schemaName) {
this.schemaName = schemaName;
}
public void setNamingStrategy(NamingStrategy namingStrategy);
/**
* Returns the currently bound default schema name.
*
* @return The currently bound schema name
*/
public String getSchemaName();
/**
* Sets the currently bound default schema name.
*
* @param schemaName The schema name to bind as the current default.
*/
public void setSchemaName(String schemaName);
/**
* Returns the currently bound default catalog name.
*
* @return The currently bound catalog name, or null if none.
*/
public String getCatalogName();
/**
* Sets the catalogName.
* @param catalogName The catalogName to set
* Sets the currently bound default catalog name.
*
* @param catalogName The catalog name to use as the current default.
*/
public void setCatalogName(String catalogName) {
this.catalogName = catalogName;
}
public void setCatalogName(String catalogName);
/**
* Sets the defaultCascade.
* @param defaultCascade The defaultCascade to set
* Get the currently bound default package name.
*
* @return The currently bound default package name
*/
public void setDefaultCascade(String defaultCascade) {
this.defaultCascade = defaultCascade;
}
public String getDefaultPackage();
/**
* sets the default access strategy
* @param defaultAccess the default access strategy.
* Set the current default package name.
*
* @param defaultPackage The package name to set as the current default.
*/
public void setDefaultAccess(String defaultAccess) {
this.defaultAccess = defaultAccess;
}
public String getDefaultAccess() {
return defaultAccess;
}
public void addQuery(String name, NamedQueryDefinition query) throws MappingException {
checkQueryExist(name);
queries.put( name.intern(), query );
}
public void addSQLQuery(String name, NamedSQLQueryDefinition query) throws MappingException {
checkQueryExist(name);
sqlqueries.put( name.intern(), query );
}
private void checkQueryExist(String name) throws MappingException {
if ( sqlqueries.containsKey(name) || queries.containsKey(name) ) {
throw new DuplicateMappingException("query", name);
}
}
public void addResultSetMapping(ResultSetMappingDefinition sqlResultSetMapping) {
final String name = sqlResultSetMapping.getName();
if ( resultSetMappings.containsKey(name) ) {
throw new DuplicateMappingException("resultSet", name);
}
resultSetMappings.put(name, sqlResultSetMapping);
}
public ResultSetMappingDefinition getResultSetMapping(String name) {
return (ResultSetMappingDefinition) resultSetMappings.get(name);
}
public NamedQueryDefinition getQuery(String name) {
return (NamedQueryDefinition) queries.get(name);
}
public void addSecondPass(SecondPass sp) {
addSecondPass(sp, false);
}
public void addSecondPass(SecondPass sp, boolean onTopOfTheQueue) {
if (onTopOfTheQueue) {
secondPasses.add(0, sp);
}
else {
secondPasses.add(sp);
}
}
public void setDefaultPackage(String defaultPackage);
/**
* Returns the autoImport.
* @return boolean
* Determine whether auto importing of entity names is currently enabled.
*
* @return True if currently enabled; false otherwise.
*/
public boolean isAutoImport() {
return autoImport;
}
public boolean isAutoImport();
/**
* Sets the autoImport.
* @param autoImport The autoImport to set
* Set whether to enable auto importing of entity names.
*
* @param autoImport True to enable; false to diasable.
* @see #addImport
*/
public void setAutoImport(boolean autoImport) {
this.autoImport = autoImport;
}
void addUniquePropertyReference(String referencedClass, String propertyName) {
PropertyReference upr = new PropertyReference();
upr.referencedClass = referencedClass;
upr.propertyName = propertyName;
upr.unique = true;
propertyReferences.add(upr);
}
void addPropertyReference(String referencedClass, String propertyName) {
PropertyReference upr = new PropertyReference();
upr.referencedClass = referencedClass;
upr.propertyName = propertyName;
propertyReferences.add(upr);
}
private String buildTableNameKey(String schema, String catalog, String finalName) {
StringBuffer keyBuilder = new StringBuffer();
if (schema != null) keyBuilder.append( schema );
keyBuilder.append( ".");
if (catalog != null) keyBuilder.append( catalog );
keyBuilder.append( ".");
keyBuilder.append( finalName );
return keyBuilder.toString();
}
static final class PropertyReference implements Serializable {
String referencedClass;
String propertyName;
boolean unique;
}
public void setAutoImport(boolean autoImport);
/**
* @return Returns the defaultPackage.
* Determine whether default laziness is currently enabled.
*
* @return True if enabled, false otherwise.
*/
public String getDefaultPackage() {
return defaultPackage;
}
public boolean isDefaultLazy();
/**
* @param defaultPackage The defaultPackage to set.
* Set whether to enable default laziness.
*
* @param defaultLazy True to enable, false to disable.
*/
public void setDefaultPackage(String defaultPackage) {
this.defaultPackage = defaultPackage;
}
public void setDefaultLazy(boolean defaultLazy);
public NamingStrategy getNamingStrategy() {
return namingStrategy;
}
/**
* Get the current default cascade style.
*
* @return The current default cascade style.
*/
public String getDefaultCascade();
public void addTypeDef(String typeName, String typeClass, Properties paramMap) {
TypeDef def = new TypeDef(typeClass, paramMap);
typeDefs.put(typeName, def);
log.debug("Added " + typeName + " with class " + typeClass);
}
/**
* Sets the current default cascade style.
* .
* @param defaultCascade The cascade style to set as the current default.
*/
public void setDefaultCascade(String defaultCascade);
public TypeDef getTypeDef(String typeName) {
return (TypeDef) typeDefs.get(typeName);
}
/**
* Get the current default property access style.
*
* @return The current default property access style.
*/
public String getDefaultAccess();
public Iterator iterateCollections() {
return collections.values().iterator();
}
/**
* Sets the current default property access style.
*
* @param defaultAccess The access style to use as the current default.
*/
public void setDefaultAccess(String defaultAccess);
public Iterator iterateTables() {
return tables.values().iterator();
}
public Map getFilterDefinitions() {
return filterDefinitions;
}
/**
* Retrieves an iterator over the entity metadata present in this repository.
*
* @return Iterator over class metadata.
*/
public Iterator iterateClasses();
public void addFilterDefinition(FilterDefinition definition) {
filterDefinitions.put( definition.getFilterName(), definition );
}
/**
* Retrieves the entity mapping metadata for the given entity name.
*
* @param entityName The entity name for which to retrieve the metadata.
* @return The entity mapping metadata, or null if none found matching given entity name.
*/
public PersistentClass getClass(String entityName);
public FilterDefinition getFilterDefinition(String name) {
return (FilterDefinition) filterDefinitions.get(name);
}
/**
* Retrieves the entity mapping metadata for the given entity name, potentially accounting
* for imports.
*
* @param entityName The entity name for which to retrieve the metadata.
* @return The entity mapping metadata, or null if none found matching given entity name.
*/
public PersistentClass locatePersistentClassByEntityName(String entityName);
public Map getFetchProfiles() {
return fetchProfiles;
}
/**
* Add entity mapping metadata.
*
* @param persistentClass The entity metadata
* @throws DuplicateMappingException Indicates there4 was already an extry
* corresponding to the given entity name.
*/
public void addClass(PersistentClass persistentClass) throws DuplicateMappingException;
public FetchProfile findOrCreateFetchProfile(String name) {
FetchProfile profile = ( FetchProfile ) fetchProfiles.get( name );
if ( profile == null ) {
profile = new FetchProfile( name );
fetchProfiles.put( name, profile );
}
return profile;
}
/**
* Adds an import (HQL entity rename) to the repository.
*
* @param entityName The entity name being renamed.
* @param rename The rename
* @throws DuplicateMappingException If rename already is mapped to another
* entity name in this repository.
*/
public void addImport(String entityName, String rename) throws DuplicateMappingException;
public boolean isDefaultLazy() {
return defaultLazy;
}
public void setDefaultLazy(boolean defaultLazy) {
this.defaultLazy = defaultLazy;
}
/**
* Retrieves the collection mapping metadata for the given collection role.
*
* @param role The collection role for which to retrieve the metadata.
* @return The collection mapping metadata, or null if no matching collection role found.
*/
public Collection getCollection(String role);
public void addToExtendsQueue(ExtendsQueueEntry entry) {
extendsQueue.put( entry, null );
}
/**
* Returns an iterator over collection metadata.
*
* @return Iterator over collection metadata.
*/
public Iterator iterateCollections();
public PersistentClass locatePersistentClassByEntityName(String entityName) {
PersistentClass persistentClass = ( PersistentClass ) classes.get( entityName );
if ( persistentClass == null ) {
String actualEntityName = ( String ) imports.get( entityName );
if ( StringHelper.isNotEmpty( actualEntityName ) ) {
persistentClass = ( PersistentClass ) classes.get( actualEntityName );
}
}
return persistentClass;
}
/**
* Add collection mapping metadata to this repository.
*
* @param collection The collection metadata
* @throws DuplicateMappingException Indicates there was already an entry
* corresponding to the given collection role
*/
public void addCollection(Collection collection) throws DuplicateMappingException;
public void addAuxiliaryDatabaseObject(AuxiliaryDatabaseObject auxiliaryDatabaseObject) {
auxiliaryDatabaseObjects.add( auxiliaryDatabaseObject );
}
/**
* Returns the named table metadata.
*
* @param schema The named schema in which the table belongs (or null).
* @param catalog The named catalog in which the table belongs (or null).
* @param name The table name
* @return The table metadata, or null.
*/
public Table getTable(String schema, String catalog, String name);
/**
* Returns an iterator over table metadata.
*
* @return Iterator over table metadata.
*/
public Iterator iterateTables();
/**
* Adds table metedata to this repository returning the created
* metadata instance.
*
* @param schema The named schema in which the table belongs (or null).
* @param catalog The named catalog in which the table belongs (or null).
* @param name The table name
* @param subselect A select statement wwich defines a logical table, much
* like a DB view.
* @param isAbstract Is the table abstract (i.e. not really existing in the DB)?
* @return The created table metadata, or the existing reference.
*/
public Table addTable(String schema, String catalog, String name, String subselect, boolean isAbstract);
/**
* Adds a 'denormalized table' to this repository.
*
* @param schema The named schema in which the table belongs (or null).
* @param catalog The named catalog in which the table belongs (or null).
* @param name The table name
* @param isAbstract Is the table abstract (i.e. not really existing in the DB)?
* @param subselect A select statement wwich defines a logical table, much
* like a DB view.
* @param includedTable ???
* @return The created table metadata.
* @throws DuplicateMappingException If such a table mapping already exists.
*/
public Table addDenormalizedTable(String schema, String catalog, String name, boolean isAbstract, String subselect, Table includedTable)
throws DuplicateMappingException;
/**
* Get named query metadata by name.
*
* @param name The named query name
* @return The query metadata, or null.
*/
public NamedQueryDefinition getQuery(String name);
/**
* Adds metadata for a named query to this repository.
*
* @param name The name
* @param query The metadata
* @throws DuplicateMappingException If a query already exists with that name.
*/
public void addQuery(String name, NamedQueryDefinition query) throws DuplicateMappingException;
/**
* Get named SQL query metadata.
*
* @param name The named SQL query name.
* @return The meatdata, or null if none found.
*/
public NamedSQLQueryDefinition getSQLQuery(String name);
/**
* Adds metadata for a named SQL query to this repository.
*
* @param name The name
* @param query The metadata
* @throws DuplicateMappingException If a query already exists with that name.
*/
public void addSQLQuery(String name, NamedSQLQueryDefinition query) throws DuplicateMappingException;
/**
* Get the metadata for a named SQL result set mapping.
*
* @param name The mapping name.
* @return The SQL result set mapping metadat, or null if none found.
*/
public ResultSetMappingDefinition getResultSetMapping(String name);
/**
* Adds the metadata for a named SQL result set mapping to this repository.
*
* @param sqlResultSetMapping The metadata
* @throws DuplicateMappingException If metadata for another SQL result mapping was
* already found under the given name.
*/
public void addResultSetMapping(ResultSetMappingDefinition sqlResultSetMapping) throws DuplicateMappingException;
/**
* Retrieve a type definition by name.
*
* @param typeName The name of the type definition to retrieve.
* @return The type definition, or null if none found.
*/
public TypeDef getTypeDef(String typeName);
/**
* Adds a type definition to this metadata repository.
*
* @param typeName The type name.
* @param typeClass The class implementing the {@link org.hibernate.type.Type} contract.
* @param paramMap Map of parameters to be used to configure the type after instantiation.
*/
public void addTypeDef(String typeName, String typeClass, Properties paramMap);
/**
* Retrieves the copmplete map of filter definitions.
*
* @return The filter definition map.
*/
public Map getFilterDefinitions();
/**
* Retrieves a filter definition by name.
*
* @param name The name of the filter defintion to retrieve.
* @return The filter definition, or null.
*/
public FilterDefinition getFilterDefinition(String name);
/**
* Adds a filter definition to this repository.
*
* @param definition The filter definition to add.
*/
public void addFilterDefinition(FilterDefinition definition);
/**
* Retrieves a fetch profile by either finding one currently in this repository matching the given name
* or by creating one (and adding it).
*
* @param name The name of the profile.
* @return The fetch profile metadata.
*/
public FetchProfile findOrCreateFetchProfile(String name);
/**
* Retrieves an iterator over the metadata pertaining to all auxilary database objects int this repository.
*
* @return Iterator over the auxilary database object metadata.
*/
public Iterator iterateAuxliaryDatabaseObjects();
/**
* Same as {@link #iterateAuxliaryDatabaseObjects()} except that here the iterator is reversed.
*
* @return The reversed iterator.
*/
public ListIterator iterateAuxliaryDatabaseObjectsInReverse();
/**
* Add metadata pertaining to an auxilary database object to this repository.
*
* @param auxiliaryDatabaseObject The metadata.
*/
public void addAuxiliaryDatabaseObject(AuxiliaryDatabaseObject auxiliaryDatabaseObject);
/**
* Get the logical table name mapped for the given physical table.
*
* @param table The table for which to determine the logical name.
* @return The logical name.
* @throws MappingException Indicates that no logical name was bound for the given physical table.
*/
public String getLogicalTableName(Table table) throws MappingException;
/**
* Adds a table binding to this repository.
*
* @param schema The schema in which the table belongs (may be null).
* @param catalog The catalog in which the table belongs (may be null).
* @param logicalName The logical table name.
* @param physicalName The physical table name.
* @param denormalizedSuperTable ???
* @throws DuplicateMappingException Indicates physical table was already bound to another logical name.
*/
public void addTableBinding(
String schema, String catalog, String logicalName, String physicalName, Table denormalizedSuperTable
) {
String key = buildTableNameKey( schema, catalog, physicalName );
TableDescription tableDescription = new TableDescription(
logicalName, denormalizedSuperTable
);
TableDescription oldDescriptor = (TableDescription) tableNameBinding.put( key, tableDescription );
if ( oldDescriptor != null && ! oldDescriptor.logicalName.equals( logicalName ) ) {
//TODO possibly relax that
throw new MappingException("Same physical table name reference several logical table names: "
+ physicalName + " => " + "'" + oldDescriptor.logicalName + "' and '" + logicalName + "'");
String schema,
String catalog,
String logicalName,
String physicalName,
Table denormalizedSuperTable) throws DuplicateMappingException;
/**
* Binds the given 'physicalColumn' to the give 'logicalName' within the given 'table'.
*
* @param logicalName The logical column name binding.
* @param physicalColumn The physical column metadata.
* @param table The table metadata.
* @throws DuplicateMappingException Indicates a duplicate binding for either the physical column name
* or the logical column name.
*/
public void addColumnBinding(String logicalName, Column physicalColumn, Table table) throws DuplicateMappingException;
/**
* Find the physical column name for the given logical column name within the given table.
*
* @param logicalName The logical name binding.
* @param table The table metatdata.
* @return The physical column name.
* @throws MappingException Indicates that no such binding was found.
*/
public String getPhysicalColumnName(String logicalName, Table table) throws MappingException;
/**
* Find the logical column name against whcih the given physical column name was bound within the given table.
*
* @param physicalName The physical column name
* @param table The table metadata.
* @return The logical column name.
* @throws MappingException Indicates that no such binding was found.
*/
public String getLogicalColumnName(String physicalName, Table table) throws MappingException;
/**
* Adds a second-pass to the end of the current queue.
*
* @param sp The second pass to add.
*/
public void addSecondPass(SecondPass sp);
/**
* Adds a second pass.
* @param sp The second pass to add.
* @param onTopOfTheQueue True to add to the beginning of the queue; false to add to the end.
*/
public void addSecondPass(SecondPass sp, boolean onTopOfTheQueue);
/**
* Represents a property-ref mapping.
* <p/>
* TODO : currently needs to be exposed because Configuration needs access to it for second-pass processing
*/
public static final class PropertyReference implements Serializable {
public final String referencedClass;
public final String propertyName;
public final boolean unique;
public PropertyReference(String referencedClass, String propertyName, boolean unique) {
this.referencedClass = referencedClass;
this.propertyName = propertyName;
this.unique = unique;
}
}
public void addColumnBinding(String logicalName, Column finalColumn, Table table) {
ColumnNames binding = (ColumnNames) columnNameBindingPerTable.get(table);
if (binding == null) {
binding = new ColumnNames();
columnNameBindingPerTable.put(table, binding);
}
String oldFinalName = (String) binding.logicalToPhysical.put(
logicalName.toLowerCase(),
finalColumn.getQuotedName()
);
if ( oldFinalName != null &&
! ( finalColumn.isQuoted() ?
oldFinalName.equals( finalColumn.getQuotedName() ) :
oldFinalName.equalsIgnoreCase( finalColumn.getQuotedName() ) ) ) {
//TODO possibly relax that
throw new MappingException("Same logical column name referenced by different physical ones: "
+ table.getName() + "." + logicalName + " => '" + oldFinalName + "' and '" + finalColumn.getQuotedName() + "'" );
}
String oldLogicalName = (String) binding.physicalToLogical.put(
finalColumn.getQuotedName(),
logicalName
);
if ( oldLogicalName != null && ! oldLogicalName.equals( logicalName ) ) {
//TODO possibly relax that
throw new MappingException("Same physical column represented by different logical column names: "
+ table.getName() + "." + finalColumn.getQuotedName() + " => '" + oldLogicalName + "' and '" + logicalName + "'");
}
}
/**
* Adds a property reference binding to this repository.
*
* @param referencedClass The referenced entity name.
* @param propertyName The referenced property name.
*/
public void addPropertyReference(String referencedClass, String propertyName);
private String getLogicalTableName(String schema, String catalog, String physicalName) {
String key = buildTableNameKey( schema, catalog, physicalName );
TableDescription descriptor = (TableDescription) tableNameBinding.get( key );
if (descriptor == null) {
throw new MappingException( "Unable to find physical table: " + physicalName);
}
return descriptor.logicalName;
}
/**
* Adds a property reference binding to this repository where said proeprty reference is marked as unique.
*
* @param referencedClass The referenced entity name.
* @param propertyName The referenced property name.
*/
public void addUniquePropertyReference(String referencedClass, String propertyName);
public String getPhysicalColumnName(String logicalName, Table table) {
logicalName = logicalName.toLowerCase();
String finalName = null;
Table currentTable = table;
do {
ColumnNames binding = (ColumnNames) columnNameBindingPerTable.get(currentTable);
if (binding != null) {
finalName = (String) binding.logicalToPhysical.get( logicalName );
}
String key = buildTableNameKey( currentTable.getSchema(), currentTable.getCatalog(), currentTable.getName() );
TableDescription description = (TableDescription) tableNameBinding.get(key);
if (description != null) currentTable = description.denormalizedSupertable;
}
while (finalName == null && currentTable != null);
if (finalName == null) {
throw new MappingException( "Unable to find column with logical name "
+ logicalName + " in table " + table.getName() );
}
return finalName;
}
public String getLogicalColumnName(String physicalName, Table table) {
String logical = null;
Table currentTable = table;
TableDescription description = null;
do {
ColumnNames binding = (ColumnNames) columnNameBindingPerTable.get(currentTable);
if (binding != null) {
logical = (String) binding.physicalToLogical.get( physicalName );
}
String key = buildTableNameKey( currentTable.getSchema(), currentTable.getCatalog(), currentTable.getName() );
description = (TableDescription) tableNameBinding.get(key);
if (description != null) currentTable = description.denormalizedSupertable;
}
while (logical == null && currentTable != null && description != null);
if (logical == null) {
throw new MappingException( "Unable to find logical column name from physical name "
+ physicalName + " in table " + table.getName() );
}
return logical;
}
public String getLogicalTableName(Table table) {
return getLogicalTableName( table.getQuotedSchema(), table.getCatalog(), table.getQuotedName() );
}
static public class ColumnNames implements Serializable {
//<String, String>
public Map logicalToPhysical = new HashMap();
//<String, String>
public Map physicalToLogical = new HashMap();
public ColumnNames() {
}
}
static public class TableDescription implements Serializable {
public TableDescription(String logicalName, Table denormalizedSupertable) {
this.logicalName = logicalName;
this.denormalizedSupertable = denormalizedSupertable;
}
public String logicalName;
public Table denormalizedSupertable;
}
/**
* Adds an entry to the extends queue queue.
*
* @param entry The entry to add.
*/
public void addToExtendsQueue(ExtendsQueueEntry entry);
}

View File

@ -420,7 +420,7 @@ public final class SessionFactoryImpl implements SessionFactory, SessionFactoryI
// this needs to happen after persisters are all ready to go...
this.fetchProfiles = new HashMap();
itr = cfg.getFetchProfiles().values().iterator();
itr = cfg.iterateFetchProfiles();
while ( itr.hasNext() ) {
final org.hibernate.mapping.FetchProfile mappingProfile =
( org.hibernate.mapping.FetchProfile ) itr.next();