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 <version>/<timestamp> not found in " + identifier); } else { bindVersionProperty(table, identifier, column, rc, processed, mapping); } } else { log.debug("Scanning " + identifier + " for <version>/<timestamp> columns."); Iterator columnIterator = table.getColumnIterator(); while (columnIterator.hasNext()) { Column column = (Column) columnIterator.next(); boolean useIt = revengStrategy.useColumnForOptimisticLock(identifier, column.getName()); if (useIt && !processed.contains(column)) { bindVersionProperty(table, identifier, column, rc, processed, mapping); return; } } log.debug( "No columns reported while scanning for <version>/<timestamp> columns in " + identifier); } }
// bind collections. private void bindIncomingForeignKeys( PersistentClass rc, Set processed, List foreignKeys, Mapping mapping) { if (foreignKeys != null) { for (Iterator iter = foreignKeys.iterator(); iter.hasNext(); ) { ForeignKey foreignKey = (ForeignKey) iter.next(); if (revengStrategy.excludeForeignKeyAsCollection( foreignKey.getName(), TableIdentifier.create(foreignKey.getTable()), foreignKey.getColumns(), TableIdentifier.create(foreignKey.getReferencedTable()), foreignKey.getReferencedColumns())) { log.debug( "Rev.eng excluded one-to-many or one-to-one for foreignkey " + foreignKey.getName()); } else if (revengStrategy.isOneToOne(foreignKey)) { Property property = bindOneToOne(rc, foreignKey.getTable(), foreignKey, processed, false, true); rc.addProperty(property); } else { Property property = bindOneToMany(rc, foreignKey, processed, mapping); rc.addProperty(property); } } } }
private Property bindOneToOne( PersistentClass rc, Table targetTable, ForeignKey fk, Set processedColumns, boolean constrained, boolean inverseProperty) { OneToOne value = new OneToOne(targetTable, rc); value.setReferencedEntityName( revengStrategy.tableToClassName(TableIdentifier.create(targetTable))); boolean isUnique = isUniqueReference(fk); String propertyName = null; if (inverseProperty) { propertyName = revengStrategy.foreignKeyToInverseEntityName( fk.getName(), TableIdentifier.create(fk.getReferencedTable()), fk.getReferencedColumns(), TableIdentifier.create(targetTable), fk.getColumns(), isUnique); } else { propertyName = revengStrategy.foreignKeyToEntityName( fk.getName(), TableIdentifier.create(fk.getReferencedTable()), fk.getReferencedColumns(), TableIdentifier.create(targetTable), fk.getColumns(), isUnique); } Iterator columns = fk.getColumnIterator(); while (columns.hasNext()) { Column fkcolumn = (Column) columns.next(); checkColumn(fkcolumn); value.addColumn(fkcolumn); processedColumns.add(fkcolumn); } value.setFetchMode(FetchMode.SELECT); value.setConstrained(constrained); value.setForeignKeyType( constrained ? ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT : ForeignKeyDirection.FOREIGN_KEY_TO_PARENT); return makeEntityProperty(propertyName, true, targetTable, fk, value, inverseProperty); // return makeProperty(TableIdentifier.create(targetTable), propertyName, value, // true, true, value.getFetchMode() != FetchMode.JOIN, null, null); }
private Property makeCollectionProperty( String propertyName, boolean mutable, Table table, ForeignKey fk, Collection value, boolean inverseProperty) { AssociationInfo fkei = inverseProperty ? revengStrategy.foreignKeyToInverseAssociationInfo(fk) : revengStrategy.foreignKeyToAssociationInfo(fk); String fetchMode = null; String cascade = null; boolean update = mutable; boolean insert = mutable; if (fkei != null) { cascade = fkei.getCascade(); if (cascade == null) cascade = "all"; // To ensure collections cascade to be compatible with Seam-gen and previous // behavior. if (fkei.getUpdate() != null) { update = fkei.getUpdate().booleanValue(); } if (fkei.getInsert() != null) { insert = fkei.getInsert().booleanValue(); } fetchMode = fkei.getFetch(); } if (FetchMode.JOIN.toString().equalsIgnoreCase(fetchMode)) { value.setFetchMode(FetchMode.JOIN); } else if (FetchMode.SELECT.toString().equalsIgnoreCase(fetchMode)) { value.setFetchMode(FetchMode.SELECT); } else { value.setFetchMode(FetchMode.SELECT); } return makeProperty( TableIdentifier.create(table), propertyName, value, insert, update, value.getFetchMode() != FetchMode.JOIN, cascade, null); }
private Property makeEntityProperty( String propertyName, boolean mutable, Table table, ForeignKey fk, ToOne value, boolean inverseProperty) { AssociationInfo fkei = inverseProperty ? revengStrategy.foreignKeyToInverseAssociationInfo(fk) : revengStrategy.foreignKeyToAssociationInfo(fk); String fetchMode = null; String cascade = null; boolean update = mutable; boolean insert = mutable; if (fkei != null) { cascade = fkei.getCascade(); if (fkei.getUpdate() != null) { update = fkei.getUpdate().booleanValue(); } if (fkei.getInsert() != null) { insert = fkei.getInsert().booleanValue(); } fetchMode = fkei.getFetch(); } if (FetchMode.JOIN.toString().equalsIgnoreCase(fetchMode)) { value.setFetchMode(FetchMode.JOIN); } else if (FetchMode.SELECT.toString().equalsIgnoreCase(fetchMode)) { value.setFetchMode(FetchMode.SELECT); } else { value.setFetchMode(FetchMode.SELECT); } return makeProperty( TableIdentifier.create(table), propertyName, value, insert, update, value.getFetchMode() != FetchMode.JOIN, cascade, null); }
/** * bind many-to-ones * * @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; } if (revengStrategy.excludeForeignKeyAsManytoOne( foreignKey.getName(), TableIdentifier.create(foreignKey.getTable()), foreignKey.getColumns(), TableIdentifier.create(foreignKey.getReferencedTable()), foreignKey.getReferencedColumns())) { // TODO: if many-to-one is excluded should the column be marked as processed so it won't // show up at all ? log.debug("Rev.eng excluded *-to-one for foreignkey " + foreignKey.getName()); } else if (revengStrategy.isOneToOne(foreignKey)) { Property property = bindOneToOne( rc, foreignKey.getReferencedTable(), foreignKey, processedColumns, true, false); rc.addProperty(property); } else { 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), mutable, table, foreignKey, processedColumns); rc.addProperty(property); } } }
private Property bindMeta(Property property, TableIdentifier identifier) { Iterator columnIterator = property.getValue().getColumnIterator(); while (columnIterator.hasNext()) { Column col = (Column) columnIterator.next(); Map map = revengStrategy.columnToMetaAttributes(identifier, col.getName()); if (map != null) { // TODO: merge from each column ? property.setMetaAttributes(map); } } return property; }
/* (non-Javadoc) * @see org.hibernate.tool.hbm2x.ant.ConfigurationTask#doConfiguration(org.hibernate.cfg.Configuration) */ protected void doConfiguration(Configuration configuration) { JDBCMetaDataConfiguration jmdc = (JDBCMetaDataConfiguration) configuration; super.doConfiguration(jmdc); jmdc.setPreferBasicCompositeIds(preferBasicCompositeIds); DefaultReverseEngineeringStrategy defaultStrategy = new DefaultReverseEngineeringStrategy(); ReverseEngineeringStrategy strategy = defaultStrategy; if (revengFiles != null) { OverrideRepository or = new OverrideRepository(); String[] fileNames = revengFiles.list(); for (int i = 0; i < fileNames.length; i++) { or.addFile(new File(fileNames[i])); } strategy = or.getReverseEngineeringStrategy(defaultStrategy); } if (reverseEngineeringStrategyClass != null) { strategy = loadreverseEngineeringStrategy(reverseEngineeringStrategyClass, strategy); } ReverseEngineeringSettings qqsettings = new ReverseEngineeringSettings(strategy) .setDefaultPackageName(packageName) .setDetectManyToMany(detectManyToMany) .setDetectOneToOne(detectOneToOne) .setDetectOptimisticLock(detectOptimisticLock); defaultStrategy.setSettings(qqsettings); strategy.setSettings(qqsettings); jmdc.setReverseEngineeringStrategy(strategy); jmdc.readFromJDBC(); }
/** * @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 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 <version>/<timestamp> columns in " + identifier); }
/** * 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); String compositeIdName = revengStrategy.tableToCompositeIdName(TableIdentifier.create(rc.getTable())); if (compositeIdName == null) { compositeIdName = revengStrategy.classNameToCompositeIdName(rc.getClassName()); } pkc.setComponentClassName(compositeIdName); 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), true, table, foreignKey, processedColumns); processedColumns.addAll(fkfc.columns); } else { throw new JDBCBinderException("unknown thing"); } markAsUseInEquals(property); pkc.addProperty(property); } return pkc; }
/** * @param column * @param generatedIdentifier * @return */ private String guessAndAlignType( Table table, Column column, Mapping mapping, boolean generatedIdentifier) { // 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(), generatedIdentifier); 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 PrimaryKeyInfo bindPrimaryKeyToProperties( Table table, RootClass rc, Set processed, Mapping mapping, DatabaseCollector collector) { SimpleValue id = null; String idPropertyname = null; PrimaryKeyInfo pki = new PrimaryKeyInfo(); 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); String tableIdentifierStrategyName = "assigned"; boolean naturalId; if (keyColumns.size() > 1) { log.debug( "id strategy for " + rc.getEntityName() + " since it has a multiple column primary key"); naturalId = true; id = handleCompositeKey(rc, processed, keyColumns, mapping); idPropertyname = revengStrategy.tableToIdentifierPropertyName(tableIdentifier); if (idPropertyname == null) { idPropertyname = "id"; } } else { pki.suggestedStrategy = revengStrategy.getTableIdentifierStrategyName(tableIdentifier); String suggestedStrategy = pki.suggestedStrategy; if (suggestedStrategy == null) { suggestedStrategy = collector.getSuggestedIdentifierStrategy( tableIdentifier.getCatalog(), tableIdentifier.getSchema(), tableIdentifier.getName()); if (suggestedStrategy == null) { suggestedStrategy = "assigned"; } tableIdentifierStrategyName = suggestedStrategy; } else { tableIdentifierStrategyName = suggestedStrategy; } naturalId = "assigned".equals(tableIdentifierStrategyName); Column pkc = (Column) keyColumns.get(0); checkColumn(pkc); id = bindColumnToSimpleValue(table, pkc, mapping, !naturalId); idPropertyname = revengStrategy.tableToIdentifierPropertyName(tableIdentifier); if (idPropertyname == null) { idPropertyname = revengStrategy.columnToPropertyName(tableIdentifier, pkc.getName()); } processed.add(pkc); } id.setIdentifierGeneratorStrategy(tableIdentifierStrategyName); pki.suggestedProperties = revengStrategy.getTableIdentifierProperties(tableIdentifier); id.setIdentifierGeneratorProperties(pki.suggestedProperties); if (naturalId) { id.setNullValue("undefined"); } Property property = makeProperty( tableIdentifier, makeUnique(rc, idPropertyname), id, true, true, false, null, null); rc.setIdentifierProperty(property); rc.setIdentifier(id); return pki; }
private String bindCollection( PersistentClass rc, ForeignKey fromForeignKey, ForeignKey toForeignKey, Collection collection) { ForeignKey targetKey = fromForeignKey; String collectionRole = null; boolean collectionLazy = false; boolean collectionInverse = false; TableIdentifier foreignKeyTable = null; String tableToClassName; if (toForeignKey != null) { targetKey = toForeignKey; } boolean uniqueReference = isUniqueReference(targetKey); // TODO: need to look one step further for many-to-many! foreignKeyTable = TableIdentifier.create(targetKey.getTable()); TableIdentifier foreignKeyReferencedTable = TableIdentifier.create(targetKey.getReferencedTable()); if (toForeignKey == null) { collectionRole = revengStrategy.foreignKeyToCollectionName( fromForeignKey.getName(), foreignKeyTable, fromForeignKey.getColumns(), foreignKeyReferencedTable, fromForeignKey.getReferencedColumns(), uniqueReference); tableToClassName = revengStrategy.tableToClassName(foreignKeyTable); } else { collectionRole = revengStrategy.foreignKeyToManyToManyName( fromForeignKey, TableIdentifier.create(fromForeignKey.getTable()), toForeignKey, uniqueReference); tableToClassName = revengStrategy.tableToClassName(foreignKeyReferencedTable); } collectionInverse = revengStrategy.isForeignKeyCollectionInverse( targetKey.getName(), foreignKeyTable, targetKey.getColumns(), foreignKeyReferencedTable, targetKey.getReferencedColumns()); collectionLazy = revengStrategy.isForeignKeyCollectionLazy( targetKey.getName(), foreignKeyTable, targetKey.getColumns(), foreignKeyReferencedTable, targetKey.getReferencedColumns()); 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(collectionInverse); // TODO: allow overriding this collection.setLazy(collectionLazy); collection.setFetchMode(FetchMode.SELECT); return tableToClassName; }
/** * @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 collection = new org.hibernate.mapping.List(rc); // MASTER TODO: allow overriding collection type collection.setCollectionTable(collectionTable); // CHILD+ boolean manyToMany = revengStrategy.isManyToManyTable(collectionTable); if (manyToMany) { // log.debug("Rev.eng said here is a many-to-many"); // TODO: handle "the other side should influence the name" } if (manyToMany) { ManyToOne element = new ManyToOne(collection.getCollectionTable()); // TODO: find the other foreignkey and choose the other side. Iterator foreignKeyIterator = foreignKey.getTable().getForeignKeyIterator(); List keys = new ArrayList(); while (foreignKeyIterator.hasNext()) { Object next = foreignKeyIterator.next(); if (next != foreignKey) { keys.add(next); } } if (keys.size() > 1) { throw new JDBCBinderException( "more than one other foreign key to choose from!"); // todo: handle better ? } ForeignKey fk = (ForeignKey) keys.get(0); String tableToClassName = bindCollection(rc, foreignKey, fk, collection); element.setReferencedEntityName(tableToClassName); element.addColumn(fk.getColumn(0)); collection.setElement(element); } else { String tableToClassName = bindCollection(rc, foreignKey, null, collection); OneToMany oneToMany = new OneToMany(collection.getOwner()); oneToMany.setReferencedEntityName(tableToClassName); // 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); // keyValue.setForeignKeyName("none"); // Avoid creating the foreignkey // 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, false); // needed to ensure foreign key columns has same type as the "property" column. } keyValue.addColumn(fkcolumn); } collection.setKey(keyValue); mappings.addCollection(collection); return makeCollectionProperty( StringHelper.unqualify(collection.getRole()), true, rc.getTable(), foreignKey, collection, true); // return makeProperty(TableIdentifier.create( rc.getTable() ), StringHelper.unqualify( // collection.getRole() ), collection, true, true, true, "none", null); // TODO: cascade isn't // all by default }
/** * @param manyToOneCandidates * @param mappings2 */ private void createPersistentClasses(DatabaseCollector collector, Mapping mapping) { Map manyToOneCandidates = collector.getOneToManyCandidates(); 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. }*/ if (revengStrategy.isManyToManyTable(table)) { log.debug("Ignoring " + table + " as class since rev.eng. says it is a many-to-many"); continue; } RootClass rc = new RootClass(); TableIdentifier tableIdentifier = TableIdentifier.create(table); String className = revengStrategy.tableToClassName(tableIdentifier); log.debug("Building entity " + className + " based on " + tableIdentifier); rc.setEntityName(className); rc.setClassName(className); rc.setProxyInterfaceName(rc.getEntityName()); // TODO: configurable ? rc.setLazy(true); rc.setMetaAttributes(safeMeta(revengStrategy.tableToMetaAttributes(tableIdentifier))); rc.setDiscriminatorValue(rc.getEntityName()); rc.setTable(table); try { mappings.addClass(rc); } catch (DuplicateMappingException dme) { // TODO: detect this and generate a "permutation" of it ? PersistentClass class1 = mappings.getClass(dme.getName()); Table table2 = class1.getTable(); throw new JDBCBinderException( "Duplicate class name '" + rc.getEntityName() + "' generated for '" + table + "'. Same name where generated for '" + table2 + "'"); } mappings.addImport(rc.getEntityName(), rc.getEntityName()); Set processed = new HashSet(); PrimaryKeyInfo pki = bindPrimaryKeyToProperties(table, rc, processed, mapping, collector); 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); updatePrimaryKey(rc, pki); } }