All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.java.org.hibernate.cfg.JDBCBinder Maven / Gradle / Ivy

There is a newer version: 5.6.15.Final
Show newest version
/*
 * Created on 2004-11-23
 *
 */
package org.hibernate.cfg;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.FetchMode;
import org.hibernate.MappingException;
import org.hibernate.cfg.reveng.DatabaseCollector;
import org.hibernate.cfg.reveng.JDBCReader;
import org.hibernate.cfg.reveng.JDBCToHibernateTypeHelper;
import org.hibernate.cfg.reveng.MappingsDatabaseCollector;
import org.hibernate.cfg.reveng.ReverseEngineeringStrategy;
import org.hibernate.cfg.reveng.TableIdentifier;
import org.hibernate.connection.ConnectionProvider;
import org.hibernate.engine.Mapping;
import org.hibernate.engine.Versioning;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.DependantValue;
import org.hibernate.mapping.ForeignKey;
import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.ManyToOne;
import org.hibernate.mapping.MetaAttribute;
import org.hibernate.mapping.OneToMany;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.RootClass;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.Table;
import org.hibernate.mapping.Value;
import org.hibernate.type.Type;
import org.hibernate.type.TypeFactory;
import org.hibernate.util.JoinedIterator;
import org.hibernate.util.StringHelper;


/**
 * @author max
 *
 */
public class JDBCBinder {

	private Settings settings;
	private ConnectionProvider connectionProvider;
	private static final Log log = LogFactory.getLog(JDBCBinder.class);
	
	private final Mappings mappings;
	
	private final JDBCMetaDataConfiguration cfg;
	private ReverseEngineeringStrategy revengStrategy;

	/**
	 * @param mappings
	 * @param configuration
	 */
	public JDBCBinder(JDBCMetaDataConfiguration cfg, Settings settings, Mappings mappings, ReverseEngineeringStrategy revengStrategy) {
		this.cfg = cfg;
		this.settings = settings;
		this.mappings = mappings;
		this.revengStrategy = revengStrategy;
	}

	/**
	 * 
	 */
	public void readFromDatabase(String catalog, String schema, Mapping mapping) {
		
		this.connectionProvider = settings.getConnectionProvider();
				
		try {
			
			Map oneToManyCandidates = readDatabaseSchema(catalog, schema); 
			
			createPersistentClasses(oneToManyCandidates, mapping); //move this to a different step!
		} 
		catch (SQLException e) {
			throw settings.getSQLExceptionConverter().convert(e, "Reading from database", null);
		} 
		finally	{
				if(connectionProvider!=null) connectionProvider.close();
		}
		
	}

	/**
	 * Read JDBC Metadata from the database. Does not create any classes or other ORM releated structures.
	 * 
	 * @param catalog
	 * @param schema
	 * @return
	 * @throws SQLException
	 */
	public Map readDatabaseSchema(String catalog, String schema) throws SQLException {
	  	 // use default from settings if nothing else specified.
	     catalog = catalog!=null ? catalog : settings.getDefaultCatalogName();
	     schema = schema!=null ? schema : settings.getDefaultSchemaName();
	     
	     JDBCReader reader = JDBCReaderFactory.newJDBCReader(cfg.getProperties(),settings,revengStrategy);
	     DatabaseCollector dbs = new MappingsDatabaseCollector(mappings); 
	     dbs = reader.readDatabaseSchema(dbs, catalog, schema);
	     return dbs.getOneToManyCandidates();
	}


	
	/**
	 * @param manyToOneCandidates
	 * @param mappings2
	 */
	private void createPersistentClasses(Map manyToOneCandidates, Mapping mapping) {
		
		for (Iterator iter = mappings.iterateTables(); iter.hasNext();) {
			Table table = (Table) iter.next();
			if(table.getColumnSpan()==0) {
				log.warn("Cannot create persistent class for " + table + " as no columns were found.");
				continue;
			}
			// TODO: this naively just create an entity per table
			// should have an opt-out option to mark some as helper tables, subclasses etc.
			/*if(table.getPrimaryKey()==null || table.getPrimaryKey().getColumnSpan()==0) {
			    log.warn("Cannot create persistent class for " + table + " as no primary key was found.");
                continue;
                // TODO: just create one big embedded composite id instead.
            }*/
			RootClass rc = new RootClass();
			TableIdentifier tableIdentifier = TableIdentifier.create(table);
			String className = revengStrategy.tableToClassName( tableIdentifier );
			rc.setEntityName( className );
			rc.setClassName( className );				
			rc.setProxyInterfaceName( rc.getEntityName() ); // TODO: configurable ?
			rc.setLazy(true);
			
			rc.setDiscriminatorValue( rc.getEntityName() );
			rc.setTable(table);
			mappings.addClass(rc);
			mappings.addImport( rc.getEntityName(), rc.getEntityName() );
			
			Set processed = new HashSet();
            
			bindPrimaryKeyToProperties(table, rc, processed, mapping);
			bindColumnsToVersioning(table, rc, processed, mapping);
			bindOutgoingForeignKeys(table, rc, processed);
			bindColumnsToProperties(table, rc, processed, mapping);
			List incomingForeignKeys = (List) manyToOneCandidates.get( rc.getEntityName() );
			bindIncomingForeignKeys(rc, processed, incomingForeignKeys, mapping);
		}
		
	}
		
	private void bindIncomingForeignKeys(PersistentClass rc, Set processed, List foreignKeys, Mapping mapping) {
		if(foreignKeys!=null) {
			for (Iterator iter = foreignKeys.iterator(); iter.hasNext();) {
				ForeignKey fk = (ForeignKey) iter.next();
				
				Property property = bindOneToMany(rc, fk, processed, mapping);
				rc.addProperty(property);
			}
		}
	}

    /**
     * @param table
     * @param fk
     * @param columnsToBind 
     * @param processedColumns
     * @param rc
     * @param propName 
     */
    private Property bindManyToOne(String propertyName, Table table, ForeignKey fk, Set processedColumns) {
        ManyToOne value = new ManyToOne(table);
        value.setReferencedEntityName( fk.getReferencedEntityName() );
		Iterator columns = fk.getColumnIterator();
        while ( columns.hasNext() ) {       
			Column fkcolumn = (Column) columns.next();
            checkColumn(fkcolumn);
            value.addColumn(fkcolumn);
            processedColumns.add(fkcolumn);
		}
        value.setFetchMode(FetchMode.SELECT);
        
        return makeProperty(propertyName, value, true, true, value.getFetchMode()!=FetchMode.JOIN, null, null);
     }

	/**
	 * @param rc
	 * @param processed
	 * @param table
	 * @param object
	 */
	private Property bindOneToMany(PersistentClass rc, ForeignKey foreignKey, Set processed, Mapping mapping) {
		
		Table collectionTable = foreignKey.getTable();

		Collection collection = new org.hibernate.mapping.Set(rc); // MASTER TODO: allow overriding collection type
        
		collection.setCollectionTable(collectionTable); // CHILD+
		
		boolean b = isUniqueReference(foreignKey);
		
		String collectionRole = revengStrategy.foreignKeyToCollectionName(
				foreignKey.getName(),				
				TableIdentifier.create( foreignKey.getTable() ),	
				foreignKey.getColumns(), TableIdentifier.create( foreignKey.getReferencedTable() ), foreignKey.getReferencedColumns(), 
				b
			);
        collectionRole = makeUnique(rc,collectionRole);
        
		String fullRolePath = StringHelper.qualify(rc.getEntityName(), collectionRole);
        if (mappings.getCollection(fullRolePath)!=null) {
            log.debug(fullRolePath + " found twice!");
        }
        collection.setRole(fullRolePath);  // Master.setOfChildren+ 
		collection.setInverse(true); // TODO: allow overriding this
        collection.setLazy(true); // TODO: configurable
        collection.setFetchMode(FetchMode.SELECT);
        
		OneToMany oneToMany = new OneToMany( collection.getOwner() );
		oneToMany.setReferencedEntityName( revengStrategy.tableToClassName( TableIdentifier.create( foreignKey.getTable() ) ) ); // Child
		
        mappings.addSecondPass( new JDBCCollectionSecondPass(mappings, collection) );
		collection.setElement(oneToMany);

		// bind keyvalue
		KeyValue referencedKeyValue;
		String propRef = collection.getReferencedPropertyName();
		if (propRef==null) {
			referencedKeyValue = collection.getOwner().getIdentifier();
		}
		else {
			referencedKeyValue = (KeyValue) collection.getOwner()
				.getProperty(propRef)
				.getValue();
		}

		SimpleValue keyValue = new DependantValue( collectionTable, referencedKeyValue );
		//key.setCascadeDeleteEnabled( "cascade".equals( subnode.attributeValue("on-delete") ) );
		Iterator columnIterator = foreignKey.getColumnIterator();        
		while ( columnIterator.hasNext() ) {
			Column fkcolumn = (Column) columnIterator.next();
			if(fkcolumn.getSqlTypeCode()!=null) { // TODO: user defined foreign ref columns does not have a type set.
				guessAndAlignType(collectionTable, fkcolumn, mapping); // needed to ensure foreign key columns has same type as the "property" column.
			}
			keyValue.addColumn( fkcolumn );
		}
		
		collection.setKey(keyValue);
		
		mappings.addCollection(collection);
		
		return makeProperty(collectionRole, collection, true, true, true, "all", null);
		
	}

	/** return true if this foreignkey is the only reference from this table to the same foreign table */
    private boolean isUniqueReference(ForeignKey foreignKey) {
		
    	Iterator foreignKeyIterator = foreignKey.getTable().getForeignKeyIterator();
    	while ( foreignKeyIterator.hasNext() ) {
			ForeignKey element = (ForeignKey) foreignKeyIterator.next();
			if(element!=foreignKey && element.getReferencedTable().equals(foreignKey.getReferencedTable())) {
				return false;
			}
		}
		return true;
	}

	private void bindPrimaryKeyToProperties(Table table, RootClass rc, Set processed, Mapping mapping) {
		SimpleValue id = null;
		String idPropertyname = null;
		
		List keyColumns = null;
		if (table.getPrimaryKey()!=null) {
			keyColumns = table.getPrimaryKey().getColumns();
		} 
		else {
			log.debug("No primary key found for " + table + ", using all properties as the identifier.");
			keyColumns = new ArrayList();
			Iterator iter = table.getColumnIterator();
			while (iter.hasNext() ) {
				Column col = (Column) iter.next();
				keyColumns.add(col);
			}
		}

		final TableIdentifier tableIdentifier = TableIdentifier.create(table);
		if (keyColumns.size()>1) {
			id = handleCompositeKey(rc, processed, keyColumns, mapping);
			idPropertyname = "id";
		} 
		else {
			Column pkc = (Column) keyColumns.get(0);
			checkColumn(pkc);
			
			id = bindColumnToSimpleValue(table, pkc, mapping);

			idPropertyname = revengStrategy.columnToPropertyName(tableIdentifier, pkc.getName() );
			processed.add(pkc);
		} 
		id.setIdentifierGeneratorStrategy(revengStrategy.getTableIdentifierStrategyName(tableIdentifier));
		id.setIdentifierGeneratorProperties(revengStrategy.getTableIdentifierProperties(tableIdentifier));
		if("assigned".equals(id.getIdentifierGeneratorStrategy())) {
			id.setNullValue("undefined");
		}
		
		Property property = makeProperty(makeUnique(rc,idPropertyname), id, true, true, false, null, null);
		rc.setIdentifierProperty(property);            
		rc.setIdentifier(id);
			
	}

	/**
	 * @param table
	 * @param rc
	 * @param primaryKey
	 */
	private void bindOutgoingForeignKeys(Table table, RootClass rc, Set processedColumns) {
		
		// Iterate the outgoing foreign keys and create many-to-one's 
		for(Iterator iterator = table.getForeignKeyIterator(); iterator.hasNext();) {
			ForeignKey foreignKey = (ForeignKey) iterator.next();
			
			boolean mutable = true;
            if ( contains( foreignKey.getColumnIterator(), processedColumns ) ) {
				if ( !cfg.preferBasicCompositeIds() ) continue; //it's in the pk, so skip this one
				mutable = false;	
            }
            
            boolean isUnique = isUniqueReference(foreignKey);
            String propertyName = revengStrategy.foreignKeyToEntityName(
					foreignKey.getName(), 
					TableIdentifier.create(foreignKey.getTable() ), 
					foreignKey.getColumns(), 
					TableIdentifier.create(foreignKey.getReferencedTable() ),
					foreignKey.getReferencedColumns(), 
					isUnique
				);
			
            Property property = bindManyToOne(
					makeUnique(rc, propertyName), 
					table, 
					foreignKey,
					processedColumns
				);
            property.setUpdateable(mutable);
            property.setInsertable(mutable);
			
            rc.addProperty(property);
        
		}
	}
		
	/**
	 * @param table
	 * @param rc
	 * @param primaryKey
	 */
	private void bindColumnsToProperties(Table table, RootClass rc, Set processedColumns, Mapping mapping) {
			
		for (Iterator iterator = table.getColumnIterator(); iterator.hasNext();) {
			Column column = (Column) iterator.next();
			if ( !processedColumns.contains(column) ) {
				checkColumn(column);
				
				String propertyName = revengStrategy.columnToPropertyName(TableIdentifier.create(table), column.getName() );
				
				Property property = bindBasicProperty( 
						makeUnique(rc,propertyName), 
						table, 
						column, 
						processedColumns,
						mapping
					);
				
				rc.addProperty(property);
			}			
		}
	}
	
	private void bindColumnsToVersioning(Table table, RootClass rc, Set processed, Mapping mapping) {
		TableIdentifier identifier = TableIdentifier.create(table);
		
		String optimisticLockColumnName = revengStrategy.getOptimisticLockColumnName(identifier);
		
		if(optimisticLockColumnName!=null) {
			Column column = table.getColumn(new Column(optimisticLockColumnName));
			if(column==null) {
				log.warn("Column " + column + " wanted for / not found in " + identifier);
			} else {
				bindVersionProperty(table, identifier, column, rc, processed, mapping);
			}
		} else {
			log.debug("Scanning " + identifier + " for / columns.");
			Iterator columnIterator = table.getColumnIterator();
			while(columnIterator.hasNext()) {
				Column column = (Column) columnIterator.next();
				Boolean useIt = revengStrategy.useColumnForOptimisticLock(identifier, column.getName());
				if(Boolean.TRUE==useIt && !processed.contains(column)) {
					bindVersionProperty( table, identifier, column, rc, processed, mapping );
					return; 
				}
			}
			log.debug("No columns reported while scanning for / columns in " + identifier);
		}
	}

	private void bindVersionProperty(Table table, TableIdentifier identifier, Column column, RootClass rc, Set processed, Mapping mapping) {
		
		processed.add(column);
		String propertyName = revengStrategy.columnToPropertyName( identifier, column.getName() );
		Property property = bindBasicProperty(makeUnique(rc, propertyName), table, column, processed, mapping);
		rc.addProperty(property);
		rc.setVersion(property);
		rc.setOptimisticLockMode(Versioning.OPTIMISTIC_LOCK_VERSION);
		log.debug("Column " + column.getName() + " will be used for / columns in " + identifier);
		
	}

	private Property bindBasicProperty(String propertyName, Table table, Column column, Set processedColumns, Mapping mapping) {

		SimpleValue value = bindColumnToSimpleValue( table, column, mapping );
		
		return makeProperty(propertyName, value, true, true, false, null, null);
	}

	private SimpleValue bindColumnToSimpleValue(Table table, Column column, Mapping mapping) {
		SimpleValue value = new SimpleValue(table);                
		value.addColumn(column);
		value.setTypeName(guessAndAlignType(table, column, mapping));
		return value;
	}

    /**
     * @param columnIterator
     * @param processedColumns
     * @return
     */
    private boolean contains(Iterator columnIterator, Set processedColumns) {
        while (columnIterator.hasNext() ) {
            Column element = (Column) columnIterator.next();
            if(processedColumns.contains(element) ) {
                return true;
            }
        }
        return false;
    }

	private void checkColumn(Column column) {
		if(column.getValue()!=null) {
			//throw new JDBCBinderException("Binding column twice should not happen. " + column);
		}
	}

	/**
	 * @param column
	 * @return
	 */
	private String guessAndAlignType(Table table, Column column, Mapping mapping) {
		// TODO: this method mutates the column if the types does not match...not good. 
		// maybe we should copy the column instead before calling this method.
		Integer sqlTypeCode = column.getSqlTypeCode();
		String location = "Table: " + Table.qualify(table.getCatalog(), table.getSchema(), table.getQuotedName() ) + " column: " + column.getQuotedName();
		if(sqlTypeCode==null) {
			throw new JDBCBinderException("sqltype is null for " + location);
		}
		
		String preferredHibernateType = revengStrategy.columnToHibernateTypeName(
				TableIdentifier.create(table), 
				column.getName(), 
				sqlTypeCode.intValue(),
				column.getLength(), column.getPrecision(), column.getScale(), column.isNullable()
		);
		
		Type wantedType = TypeFactory.heuristicType(preferredHibernateType);
		
		if(wantedType!=null) {
			int[] wantedSqlTypes = wantedType.sqlTypes(mapping);
			
			if(wantedSqlTypes.length>1) {
				throw new JDBCBinderException("The type " + preferredHibernateType + " found on " + location + " spans multiple columns. Only single column types allowed."); 
			}
			
			int wantedSqlType = wantedSqlTypes[0];
			if(wantedSqlType!=sqlTypeCode.intValue() ) {			
				log.debug("Sql type mismatch for " + location + " between DB and wanted hibernate type. Sql type set to " + typeCodeName( sqlTypeCode.intValue() ) + " instead of " + typeCodeName(wantedSqlType) );
				column.setSqlTypeCode(new Integer(wantedSqlType));
			}
		} 
		else {
			log.debug("No Hibernate type found for " + preferredHibernateType + ". Most likely cause is a missing UserType class.");
		}
		
		
		
		if(preferredHibernateType==null) {
			throw new JDBCBinderException("Could not find javatype for " + typeCodeName(sqlTypeCode.intValue()));
		}
        
		return preferredHibernateType;
	}

	private String typeCodeName(int sqlTypeCode) {
		return sqlTypeCode + "(" + JDBCToHibernateTypeHelper.getJDBCTypeName(sqlTypeCode) + ")";
	}

	/**
     * Basically create an [classname]Id.class and add  properties for it.
	 * @param rc
	 * @param compositeKeyColumns 
	 * @param processed
	 * @return
	 */
	private SimpleValue handleCompositeKey(RootClass rc, Set processedColumns, List keyColumns, Mapping mapping) {
		Component pkc = new Component(rc);
        pkc.setMetaAttributes(Collections.EMPTY_MAP);
        pkc.setEmbedded(false);
        pkc.setComponentClassName(revengStrategy.classNameToCompositeIdName(rc.getClassName()));
		Table table = rc.getTable();		
        List list = null;        
		if (cfg.preferBasicCompositeIds() ) {
            list = new ArrayList(keyColumns);
        } 
		else {
            list = findForeignKeys(table.getForeignKeyIterator(), keyColumns);
        }
        for (Iterator iter = list.iterator(); iter.hasNext();) {
            Object element = iter.next();
			Property property;
            if (element instanceof Column) {
                Column column = (Column) element;
                if ( processedColumns.contains(column) ) {
                    throw new JDBCBinderException("Binding column twice for primary key should not happen: " + column); 
                } 
				else {
                    checkColumn(column);
                    
                    String propertyName = revengStrategy.columnToPropertyName( TableIdentifier.create(table), column.getName() );
					property = bindBasicProperty( makeUnique(pkc, propertyName), table, column, processedColumns, mapping);
                    
                    processedColumns.add(column);
                }
            } 
			else if (element instanceof ForeignKeyForColumns) {
                ForeignKeyForColumns fkfc = (ForeignKeyForColumns) element;
                ForeignKey foreignKey = fkfc.key;
                String propertyName = revengStrategy.foreignKeyToEntityName(
						foreignKey.getName(), 
						TableIdentifier.create(foreignKey.getTable() ),
						foreignKey.getColumns(), TableIdentifier.create(foreignKey.getReferencedTable() ), foreignKey.getReferencedColumns(), true
					);
                property = bindManyToOne( makeUnique(pkc, propertyName), table, foreignKey, processedColumns);
                processedColumns.addAll(fkfc.columns);
            }
			else {
				throw new JDBCBinderException("unknown thing");
			}
			
            markAsUseInEquals(property);
            pkc.addProperty(property);
			
		}

		return pkc;
	}

    /**
     * @param property
     */
    private void markAsUseInEquals(Property property) {
        Map m = new HashMap();
        MetaAttribute ma = new MetaAttribute("use-in-equals");
        ma.addValue("true");
        m.put(ma.getName(),ma);
        property.setMetaAttributes(m);
    }

    /**
     * @param foreignKeyIterator
     * @param columns
     * @return 
     */
    private List findForeignKeys(Iterator foreignKeyIterator, List pkColumns) {
    	
    	List tempList = new ArrayList();
    	while(foreignKeyIterator.hasNext()) {
    		tempList.add(foreignKeyIterator.next());
    	}
    	
//    	Collections.reverse(tempList); 
    	
    	List result = new ArrayList();
    	Column myPkColumns[] = (Column[]) pkColumns.toArray(new Column[pkColumns.size()]);
    	
    	for (int i = 0; i < myPkColumns.length; i++) {
			
    		boolean foundKey = false;
    		foreignKeyIterator = tempList.iterator();
    		while(foreignKeyIterator.hasNext()) {
    			ForeignKey key = (ForeignKey) foreignKeyIterator.next();
    			List matchingColumns = columnMatches(myPkColumns, i, key);
    			if(matchingColumns!=null) {
    				result.add(new ForeignKeyForColumns(key, matchingColumns));
    				i+=matchingColumns.size()-1;
    				foreignKeyIterator.remove();
    				foundKey=true;
    				break;
    			} 
    		}
    		if(!foundKey) {
    			result.add(myPkColumns[i]);				
    		}
    		
		}
    	
    	return result;
    }

    private List columnMatches(Column[] myPkColumns, int offset, ForeignKey key) {
		
    	if(key.getColumnSpan()>(myPkColumns.length-offset)) {
    		return null; // not enough columns in the key
    	}
    	
    	List columns = new ArrayList();
    	for (int j = 0; j < key.getColumnSpan(); j++) {
			Column column = myPkColumns[j+offset];
			if(!column.equals(key.getColumn(j))) {
				return null;
			} else {
				columns.add(column);
			}
		}
		return columns.isEmpty()?null:columns;
	}

	static class ForeignKeyForColumns {
        
        protected final List columns;
        protected final ForeignKey key;

        public ForeignKeyForColumns(ForeignKey key, List columns) {
            this.key = key;
            this.columns = columns;
        }
    }

    private static Property makeProperty(String propertyName, Value value, boolean insertable, boolean updatable, boolean lazy, String cascade, String propertyAccessorName) {
		log.debug("Building property " + propertyName);
        Property prop = new Property();
		prop.setName(propertyName);
		prop.setValue(value);
		prop.setInsertable(insertable);
		prop.setUpdateable(updatable);
		prop.setLazy(lazy);		
		prop.setCascade(cascade==null?"none":cascade);
		prop.setPropertyAccessorName(propertyAccessorName==null?"property":propertyAccessorName);
		prop.setMetaAttributes(Collections.EMPTY_MAP);
		log.debug("Cascading " + propertyName + " with " + cascade);
		return prop;
	}
    

    /**
     * @param pkc
     * @param string
     * @return
     */
    private String makeUnique(Component clazz, String propertyName) {
        return makeUnique(clazz.getPropertyIterator(), propertyName);
    }

    private String makeUnique(PersistentClass clazz, String propertyName) {
        List list = new ArrayList();
                
        if( clazz.hasIdentifierProperty() ) {
            list.add( clazz.getIdentifierProperty() );
        }
        
        if( clazz.isVersioned() ) {
            list.add( clazz.getVersion() );
        }
        
        JoinedIterator iterator = new JoinedIterator( list.iterator(),clazz.getPropertyClosureIterator() );
        return makeUnique(iterator, propertyName);
    }
    /**
     * @param clazz
     * @param propertyName
     * @return
     */
    private static String makeUnique(Iterator props, String originalPropertyName) {
        int cnt = 0;
        String propertyName = originalPropertyName;
        Set uniqueNames = new HashSet();
        
        while ( props.hasNext() ) {
            Property element = (Property) props.next();
            uniqueNames.add( element.getName() );
        }
        
        while( uniqueNames.contains(propertyName) ) { 
            cnt++;
            propertyName = originalPropertyName + "_" + cnt;
        }
        
        return propertyName;                                
    }

    public static void bindCollectionSecondPass(
            Collection collection,
            java.util.Map persistentClasses,
            Mappings mappings,
            java.util.Map inheritedMetas) throws MappingException {

        if(collection.isOneToMany() ) {
            OneToMany oneToMany = (OneToMany) collection.getElement();
            PersistentClass persistentClass = mappings.getClass(oneToMany.getReferencedEntityName() ); 
            
            if (persistentClass==null) throw new MappingException(
                    "Association references unmapped class: " + oneToMany.getReferencedEntityName()
                );
            
            oneToMany.setAssociatedClass(persistentClass); // Child            
        }
        
    }

    static class JDBCCollectionSecondPass extends CollectionSecondPass {

        /**
         * @param mappings
         * @param coll
         */
        JDBCCollectionSecondPass(Mappings mappings, Collection coll) {
            super(mappings, coll);
        }

        /* (non-Javadoc)
         * @see org.hibernate.cfg.HbmBinder.SecondPass#secondPass(java.util.Map, java.util.Map)
         */
        public void secondPass(Map persistentClasses, Map inheritedMetas) throws MappingException {
            JDBCBinder.bindCollectionSecondPass(collection, persistentClasses, mappings, inheritedMetas);            
        }        
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy