public void testReadOnlySpecificSchema() {

    JDBCMetaDataConfiguration configuration = new JDBCMetaDataConfiguration();

    OverrideRepository or = new OverrideRepository();
    or.addSchemaSelection(new SchemaSelection(null, SCHEMA));
    configuration.setReverseEngineeringStrategy(
        or.getReverseEngineeringStrategy(new DefaultReverseEngineeringStrategy()));
    configuration.readFromJDBC();

    List<Table> tables = getTables(configuration);

    assertEquals(2, tables.size());

    Table catchild = (Table) tables.get(0);
    Table catmaster = (Table) tables.get(1);

    if (catchild.getName().equals(TABLE2)) {
      catchild = (Table) tables.get(1);
      catmaster = (Table) tables.get(0);
    }

    TableIdentifier masterid = TableIdentifier.create(catmaster);
    TableIdentifier childid = TableIdentifier.create(catchild);

    assertEquals(new TableIdentifier(null, SCHEMA, TABLE1), childid);
    assertEquals(new TableIdentifier(null, SCHEMA, TABLE2), masterid);
  }
예제 #2
0
  // 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);
        }
      }
    }
  }
예제 #3
0
  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);
  }
예제 #4
0
  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);
    }
  }
예제 #5
0
  private Property bindBasicProperty(
      String propertyName, Table table, Column column, Set processedColumns, Mapping mapping) {

    SimpleValue value = bindColumnToSimpleValue(table, column, mapping, false);

    return makeProperty(
        TableIdentifier.create(table), propertyName, value, true, true, false, null, null);
  }
예제 #6
0
  /**
   * 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);
      }
    }
  }
예제 #7
0
  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);
  }
예제 #8
0
  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);
  }
예제 #9
0
  /**
   * @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);
      }
    }
  }
예제 #10
0
  /**
   * 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;
  }
예제 #11
0
  /**
   * @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;
  }
예제 #12
0
  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;
  }
예제 #13
0
  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;
  }
예제 #14
0
  /**
   * @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);
    }
  }