예제 #1
0
 private SimpleValue bindColumnToSimpleValue(
     Table table, Column column, Mapping mapping, boolean generatedIdentifier) {
   SimpleValue value = new SimpleValue(table);
   value.addColumn(column);
   value.setTypeName(guessAndAlignType(table, column, mapping, generatedIdentifier));
   return value;
 }
예제 #2
0
  public void copyTypeFrom(SimpleValue sourceValue) {
    setTypeName(sourceValue.getTypeName());
    setTypeParameters(sourceValue.getTypeParameters());

    type = sourceValue.type;
    attributeConverterDefinition = sourceValue.attributeConverterDefinition;
  }
예제 #3
0
  @Override
  protected void addColumnBinding(SimpleValue value) {
    if (StringHelper.isEmpty(mappedBy)) {
      // was the column explicitly quoted in the mapping/annotation
      // TODO: in metamodel, we need to better split global quoting and explicit quoting w/ respect
      // to logical names
      boolean isLogicalColumnQuoted = StringHelper.isQuoted(getLogicalColumnName());

      final ObjectNameNormalizer nameNormalizer = getBuildingContext().getObjectNameNormalizer();
      final String logicalColumnName =
          nameNormalizer.normalizeIdentifierQuotingAsString(getLogicalColumnName());
      final String referencedColumn =
          nameNormalizer.normalizeIdentifierQuotingAsString(getReferencedColumn());
      final String unquotedLogColName = StringHelper.unquote(logicalColumnName);
      final String unquotedRefColumn = StringHelper.unquote(referencedColumn);

      String logicalCollectionColumnName =
          StringHelper.isNotEmpty(unquotedLogColName)
              ? unquotedLogColName
              : getPropertyName() + '_' + unquotedRefColumn;
      logicalCollectionColumnName =
          getBuildingContext()
              .getMetadataCollector()
              .getDatabase()
              .getJdbcEnvironment()
              .getIdentifierHelper()
              .toIdentifier(logicalCollectionColumnName, isLogicalColumnQuoted)
              .render();
      getBuildingContext()
          .getMetadataCollector()
          .addColumnNameBinding(value.getTable(), logicalCollectionColumnName, getMappingColumn());
    }
  }
예제 #4
0
  private void updatePrimaryKey(RootClass rc, PrimaryKeyInfo pki) {
    SimpleValue idValue = (SimpleValue) rc.getIdentifierProperty().getValue();

    Properties defaultStrategyProperties = new Properties();
    Property constrainedOneToOne = getConstrainedOneToOne(rc);
    if (constrainedOneToOne != null) {
      if (pki.suggestedStrategy == null) {
        idValue.setIdentifierGeneratorStrategy("foreign");
      }

      if (pki.suggestedProperties == null) {
        defaultStrategyProperties.setProperty("property", constrainedOneToOne.getName());
        idValue.setIdentifierGeneratorProperties(defaultStrategyProperties);
      }
    }
  }
  /**
   * Tests that single- and multi-column user type mappings work correctly. Also Checks that the
   * "sqlType" property is honoured.
   */
  public void testUserTypeMappings() {
    DefaultGrailsDomainConfiguration config = getDomainConfig(MULTI_COLUMN_USER_TYPE_DEFINITION);
    PersistentClass persistentClass = config.getClassMapping("Item");

    // First check the "name" property and its associated column.
    Property nameProperty = persistentClass.getProperty("name");
    assertEquals(1, nameProperty.getColumnSpan());
    assertEquals("name", nameProperty.getName());

    Column column = (Column) nameProperty.getColumnIterator().next();
    assertEquals("s_name", column.getName());
    assertEquals("text", column.getSqlType());

    // Next the "other" property.
    Property otherProperty = persistentClass.getProperty("other");
    assertEquals(1, otherProperty.getColumnSpan());
    assertEquals("other", otherProperty.getName());

    column = (Column) otherProperty.getColumnIterator().next();
    assertEquals("other", column.getName());
    assertEquals("wrapper-characters", column.getSqlType());
    assertEquals(MyUserType.class.getName(), column.getValue().getType().getName());
    assertTrue(column.getValue() instanceof SimpleValue);
    SimpleValue v = (SimpleValue) column.getValue();
    assertEquals("myParam1", v.getTypeParameters().get("param1"));
    assertEquals("myParam2", v.getTypeParameters().get("param2"));

    // And now for the "price" property, which should have two
    // columns.
    Property priceProperty = persistentClass.getProperty("price");
    assertEquals(2, priceProperty.getColumnSpan());
    assertEquals("price", priceProperty.getName());

    Iterator<?> colIter = priceProperty.getColumnIterator();
    column = (Column) colIter.next();
    assertEquals("value", column.getName());
    assertNull("SQL type should have been 'null' for 'value' column.", column.getSqlType());

    column = (Column) colIter.next();
    assertEquals("currency_code", column.getName());
    assertEquals("text", column.getSqlType());
  }
예제 #6
0
  public void /*test*/ AddNewProperty() {
    System.out.println("******************* testAddNewProperty ********************");
    PersistentClass userMapping = HibernateUtil.getClassMapping(User.class);

    Column column = new Column();
    column.setName("MOTTO");
    column.setNullable(false);
    column.setUnique(true);
    column.setSqlType("VARCHAR");
    userMapping.getTable().addColumn(column);

    SimpleValue value = new SimpleValue();
    value.setTable(userMapping.getTable());
    value.addColumn(column);
    value.setTypeName("string");

    Property prop = new Property();
    prop.setValue(value);
    prop.setName("motto");
    prop.setPropertyAccessorName("field");
    prop.setNodeName(prop.getName());
    userMapping.addProperty(prop);

    HibernateUtil.rebuildSessionFactory();

    ClassMetadata metadata = HibernateUtil.getClassMetadata(User.class);
    String[] propNames = metadata.getPropertyNames();
    boolean mottoFound = false;
    for (int i = 0; i < propNames.length; i++) {
      String propName = propNames[i];
      if (propName.equalsIgnoreCase("motto")) {
        mottoFound = true;
        break;
      }
    }

    assertTrue(mottoFound);
  }
예제 #7
0
  /**
   * Builds the <code>Join</code> instance for the mapped by side of a <i>OneToOne</i> association
   * using a join tables.
   *
   * <p>Note:<br>
   *
   * <ul>
   *   <li>From the mappedBy side we should not create the PK nor the FK, this is handled from the
   *       other side.
   *   <li>This method is a dirty dupe of EntityBinder.bindSecondaryTable</i>.
   */
  private Join buildJoinFromMappedBySide(
      PersistentClass persistentClass, Property otherSideProperty, Join originalJoin) {
    Join join = new Join();
    join.setPersistentClass(persistentClass);

    // no check constraints available on joins
    join.setTable(originalJoin.getTable());
    join.setInverse(true);
    SimpleValue key =
        new DependantValue(mappings, join.getTable(), persistentClass.getIdentifier());
    // TODO support @ForeignKey
    join.setKey(key);
    join.setSequentialSelect(false);
    // TODO support for inverse and optional
    join.setOptional(true); // perhaps not quite per-spec, but a Good Thing anyway
    key.setCascadeDeleteEnabled(false);
    Iterator mappedByColumns = otherSideProperty.getValue().getColumnIterator();
    while (mappedByColumns.hasNext()) {
      Column column = (Column) mappedByColumns.next();
      Column copy = new Column();
      copy.setLength(column.getLength());
      copy.setScale(column.getScale());
      copy.setValue(key);
      copy.setName(column.getQuotedName());
      copy.setNullable(column.isNullable());
      copy.setPrecision(column.getPrecision());
      copy.setUnique(column.isUnique());
      copy.setSqlType(column.getSqlType());
      copy.setCheckConstraint(column.getCheckConstraint());
      copy.setComment(column.getComment());
      copy.setDefaultValue(column.getDefaultValue());
      key.addColumn(copy);
    }
    persistentClass.addJoin(join);
    return join;
  }
  @SuppressWarnings({"unchecked"})
  public void doSecondPass(Map persistentClasses) throws MappingException {
    PersistentClass referencedPersistentClass =
        (PersistentClass) persistentClasses.get(referencedEntityName);
    // TODO better error names
    if (referencedPersistentClass == null) {
      throw new AnnotationException("Unknown entity name: " + referencedEntityName);
    }
    if (!(referencedPersistentClass.getIdentifier() instanceof Component)) {
      throw new AssertionFailure(
          "Unexpected identifier type on the referenced entity when mapping a @MapsId: "
              + referencedEntityName);
    }
    Component referencedComponent = (Component) referencedPersistentClass.getIdentifier();
    Iterator<Property> properties = referencedComponent.getPropertyIterator();

    // prepare column name structure
    boolean isExplicitReference = true;
    Map<String, Ejb3JoinColumn> columnByReferencedName =
        new HashMap<String, Ejb3JoinColumn>(joinColumns.length);
    for (Ejb3JoinColumn joinColumn : joinColumns) {
      final String referencedColumnName = joinColumn.getReferencedColumn();
      if (referencedColumnName == null
          || BinderHelper.isEmptyAnnotationValue(referencedColumnName)) {
        break;
      }
      // JPA 2 requires referencedColumnNames to be case insensitive
      columnByReferencedName.put(referencedColumnName.toLowerCase(), joinColumn);
    }
    // try default column orientation
    int index = 0;
    if (columnByReferencedName.isEmpty()) {
      isExplicitReference = false;
      for (Ejb3JoinColumn joinColumn : joinColumns) {
        columnByReferencedName.put("" + index, joinColumn);
        index++;
      }
      index = 0;
    }

    while (properties.hasNext()) {
      Property referencedProperty = properties.next();
      if (referencedProperty.isComposite()) {
        throw new AssertionFailure(
            "Unexpected nested component on the referenced entity when mapping a @MapsId: "
                + referencedEntityName);
      } else {
        Property property = new Property();
        property.setName(referencedProperty.getName());
        property.setNodeName(referencedProperty.getNodeName());
        // FIXME set optional?
        // property.setOptional( property.isOptional() );
        property.setPersistentClass(component.getOwner());
        property.setPropertyAccessorName(referencedProperty.getPropertyAccessorName());
        SimpleValue value = new SimpleValue(mappings, component.getTable());
        property.setValue(value);
        final SimpleValue referencedValue = (SimpleValue) referencedProperty.getValue();
        value.setTypeName(referencedValue.getTypeName());
        value.setTypeParameters(referencedValue.getTypeParameters());
        final Iterator<Column> columns = referencedValue.getColumnIterator();

        if (joinColumns[0].isNameDeferred()) {
          joinColumns[0].copyReferencedStructureAndCreateDefaultJoinColumns(
              referencedPersistentClass, columns, value);
        } else {
          // FIXME take care of Formula
          while (columns.hasNext()) {
            Column column = columns.next();
            final Ejb3JoinColumn joinColumn;
            String logicalColumnName = null;
            if (isExplicitReference) {
              final String columnName = column.getName();
              logicalColumnName =
                  mappings.getLogicalColumnName(columnName, referencedPersistentClass.getTable());
              // JPA 2 requires referencedColumnNames to be case insensitive
              joinColumn = columnByReferencedName.get(logicalColumnName.toLowerCase());
            } else {
              joinColumn = columnByReferencedName.get("" + index);
              index++;
            }
            if (joinColumn == null && !joinColumns[0].isNameDeferred()) {
              throw new AnnotationException(
                  isExplicitReference
                      ? "Unable to find column reference in the @MapsId mapping: "
                          + logicalColumnName
                      : "Implicit column reference in the @MapsId mapping fails, try to use explicit referenceColumnNames: "
                          + referencedEntityName);
            }
            final String columnName =
                joinColumn == null || joinColumn.isNameDeferred()
                    ? "tata_" + column.getName()
                    : joinColumn.getName();
            value.addColumn(new Column(columnName));
            column.setValue(value);
          }
        }
        component.addProperty(property);
      }
    }
  }
예제 #9
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;
  }
예제 #10
0
  /**
   * @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

  }