Пример #1
0
  /**
   * Walk the association tree for an entity, adding associations which should be join fetched to
   * the {@link #associations} inst var. This form is the entry point into the walking for a given
   * entity, starting the recursive calls into {@link
   * #walkEntityTree(org.hibernate.persister.entity.OuterJoinLoadable, String, PropertyPath ,int)}.
   *
   * @param persister The persister representing the entity to be walked.
   * @param alias The (root) alias to use for this entity/persister.
   * @param path The property path to the entity being walked
   * @param currentDepth The current join depth
   * @throws org.hibernate.MappingException ???
   */
  private void walkEntityTree(
      final OuterJoinLoadable persister,
      final String alias,
      final PropertyPath path,
      final int currentDepth)
      throws MappingException {
    int n = persister.countSubclassProperties();
    for (int i = 0; i < n; i++) {
      Type type = persister.getSubclassPropertyType(i);
      if (type.isAssociationType()) {
        walkEntityAssociationTree(
            (AssociationType) type,
            persister,
            i,
            alias,
            path,
            persister.isSubclassPropertyNullable(i),
            currentDepth);
      } else if (type.isComponentType()) {
        walkComponentTree(
            (CompositeType) type,
            i,
            0,
            persister,
            alias,
            path.append(persister.getSubclassPropertyName(i)),
            currentDepth);
      }
    }

    // if the entity has a composite identifier, see if we need to handle
    // its sub-properties separately
    final Type idType = persister.getIdentifierType();
    if (idType.isComponentType()) {
      final CompositeType cidType = (CompositeType) idType;
      if (cidType.isEmbedded()) {
        // we have an embedded composite identifier.  Most likely we need to process the composite
        // properties separately, although there is an edge case where the identifier is really
        // a simple identifier (single value) wrapped in a JPA @IdClass or even in the case of a
        // a simple identifier (single value) wrapped in a Hibernate composite type.
        //
        // We really do not have a built-in method to determine that.  However, generally the
        // persister would report that there is single, physical identifier property which is
        // explicitly at odds with the notion of "embedded composite".  So we use that for now
        if (persister.getEntityMetamodel().getIdentifierProperty().isEmbedded()) {
          walkComponentTree(cidType, -1, 0, persister, alias, path.append(""), currentDepth);
        }
      }
    }
  }
  private CriteriaInfoProvider getPathInfo(String path) {
    StringTokenizer tokens = new StringTokenizer(path, ".");
    String componentPath = "";

    // start with the 'rootProvider'
    CriteriaInfoProvider provider = nameCriteriaInfoMap.get(rootEntityName);

    while (tokens.hasMoreTokens()) {
      componentPath += tokens.nextToken();
      Type type = provider.getType(componentPath);
      if (type.isAssociationType()) {
        // CollectionTypes are always also AssociationTypes - but there's not always an associated
        // entity...
        AssociationType atype = (AssociationType) type;
        CollectionType ctype = type.isCollectionType() ? (CollectionType) type : null;
        Type elementType = (ctype != null) ? ctype.getElementType(sessionFactory) : null;
        // is the association a collection of components or value-types? (i.e a colloction of valued
        // types?)
        if (ctype != null && elementType.isComponentType()) {
          provider =
              new ComponentCollectionCriteriaInfoProvider(
                  helper.getCollectionPersister(ctype.getRole()));
        } else if (ctype != null && !elementType.isEntityType()) {
          provider = new ScalarCollectionCriteriaInfoProvider(helper, ctype.getRole());
        } else {
          provider =
              new EntityCriteriaInfoProvider(
                  (Queryable)
                      sessionFactory.getEntityPersister(
                          atype.getAssociatedEntityName(sessionFactory)));
        }

        componentPath = "";
      } else if (type.isComponentType()) {
        if (!tokens.hasMoreTokens()) {
          throw new QueryException(
              "Criteria objects cannot be created directly on components.  Create a criteria on owning entity and use a dotted property to access component property: "
                  + path);
        } else {
          componentPath += '.';
        }
      } else {
        throw new QueryException("not an association: " + componentPath);
      }
    }

    return provider;
  }
Пример #3
0
 /**
  * Walk the association tree for an entity, adding associations which should be join fetched to
  * the {@link #associations} inst var. This form is the entry point into the walking for a given
  * entity, starting the recursive calls into {@link
  * #walkEntityTree(org.hibernate.persister.entity.OuterJoinLoadable, String, PropertyPath ,int)}.
  *
  * @param persister The persister representing the entity to be walked.
  * @param alias The (root) alias to use for this entity/persister.
  * @param path The property path to the entity being walked
  * @param currentDepth The current join depth
  * @throws org.hibernate.MappingException ???
  */
 private void walkEntityTree(
     final OuterJoinLoadable persister,
     final String alias,
     final PropertyPath path,
     final int currentDepth)
     throws MappingException {
   int n = persister.countSubclassProperties();
   for (int i = 0; i < n; i++) {
     Type type = persister.getSubclassPropertyType(i);
     if (type.isAssociationType()) {
       walkEntityAssociationTree(
           (AssociationType) type,
           persister,
           i,
           alias,
           path,
           persister.isSubclassPropertyNullable(i),
           currentDepth);
     } else if (type.isComponentType()) {
       walkComponentTree(
           (CompositeType) type,
           i,
           0,
           persister,
           alias,
           path.append(persister.getSubclassPropertyName(i)),
           currentDepth);
     }
   }
 }
  FromElement createCollection(
      QueryableCollection queryableCollection,
      String role,
      int joinType,
      boolean fetchFlag,
      boolean indexed)
      throws SemanticException {
    if (!collection) {
      throw new IllegalStateException("FromElementFactory not initialized for collections!");
    }
    this.inElementsFunction = indexed;
    FromElement elem;
    this.queryableCollection = queryableCollection;
    collectionType = queryableCollection.getCollectionType();
    String roleAlias = fromClause.getAliasGenerator().createName(role);

    // Correlated subqueries create 'special' implied from nodes
    // because correlated subselects can't use an ANSI-style join
    boolean explicitSubqueryFromElement = fromClause.isSubQuery() && !implied;
    if (explicitSubqueryFromElement) {
      String pathRoot = StringHelper.root(path);
      FromElement origin = fromClause.getFromElement(pathRoot);
      if (origin == null || origin.getFromClause() != fromClause) {
        implied = true;
      }
    }

    // super-duper-classic-parser-regression-testing-mojo-magic...
    if (explicitSubqueryFromElement && DotNode.useThetaStyleImplicitJoins) {
      implied = true;
    }

    Type elementType = queryableCollection.getElementType();
    if (elementType.isEntityType()) { // A collection of entities...
      elem = createEntityAssociation(role, roleAlias, joinType);
    } else if (elementType.isComponentType()) { // A collection of components...
      JoinSequence joinSequence = createJoinSequence(roleAlias, joinType);
      elem = createCollectionJoin(joinSequence, roleAlias);
    } else { // A collection of scalar elements...
      JoinSequence joinSequence = createJoinSequence(roleAlias, joinType);
      elem = createCollectionJoin(joinSequence, roleAlias);
    }

    elem.setRole(role);
    elem.setQueryableCollection(queryableCollection);
    // Don't include sub-classes for implied collection joins or subquery joins.
    if (implied) {
      elem.setIncludeSubclasses(false);
    }

    if (explicitSubqueryFromElement) {
      elem.setInProjectionList(true); // Treat explict from elements in sub-queries properly.
    }

    if (fetchFlag) {
      elem.setFetch(true);
    }
    return elem;
  }
  private static NonIdentifierAttributeNature decode(Type type) {
    if (type.isAssociationType()) {
      AssociationType associationType = (AssociationType) type;

      if (type.isComponentType()) {
        // an any type is both an association and a composite...
        return NonIdentifierAttributeNature.ANY;
      }

      return type.isCollectionType()
          ? NonIdentifierAttributeNature.COLLECTION
          : NonIdentifierAttributeNature.ENTITY;
    } else {
      if (type.isComponentType()) {
        return NonIdentifierAttributeNature.COMPOSITE;
      }

      return NonIdentifierAttributeNature.BASIC;
    }
  }
 private boolean indicatesCollection(Type type) {
   if (type.isCollectionType()) {
     return true;
   } else if (type.isComponentType()) {
     Type[] subtypes = ((CompositeType) type).getSubtypes();
     for (int i = 0; i < subtypes.length; i++) {
       if (indicatesCollection(subtypes[i])) {
         return true;
       }
     }
   }
   return false;
 }
Пример #7
0
  protected String generateTableAlias(int n, PropertyPath path, Joinable joinable) {
    // TODO: deal with side-effects (changes to includeInResultRowList, userAliasList,
    // resultTypeList)!!!

    // for collection-of-entity, we are called twice for given "path"
    // once for the collection Joinable, once for the entity Joinable.
    // the second call will/must "consume" the alias + perform side effects according to
    // consumesEntityAlias()
    // for collection-of-other, however, there is only one call
    // it must "consume" the alias + perform side effects, despite what consumeEntityAlias() return
    // says
    //
    // note: the logic for adding to the userAliasList is still strictly based on
    // consumesEntityAlias return value
    boolean checkForSqlAlias = joinable.consumesEntityAlias();

    if (!checkForSqlAlias && joinable.isCollection()) {
      // is it a collection-of-other (component or value) ?
      CollectionPersister collectionPersister = (CollectionPersister) joinable;
      Type elementType = collectionPersister.getElementType();
      if (elementType.isComponentType() || !elementType.isEntityType()) {
        checkForSqlAlias = true;
      }
    }

    String sqlAlias = null;

    if (checkForSqlAlias) {
      final Criteria subcriteria = translator.getCriteria(path.getFullPath());
      sqlAlias = subcriteria == null ? null : translator.getSQLAlias(subcriteria);

      if (joinable.consumesEntityAlias() && !translator.hasProjection()) {
        includeInResultRowList.add(subcriteria != null && subcriteria.getAlias() != null);
        if (sqlAlias != null) {
          if (subcriteria.getAlias() != null) {
            userAliasList.add(subcriteria.getAlias());
            resultTypeList.add(translator.getResultType(subcriteria));
          }
        }
      }
    }

    if (sqlAlias == null) {
      sqlAlias = super.generateTableAlias(n + translator.getSQLAliasCount(), path, joinable);
    }

    return sqlAlias;
  }
Пример #8
0
  /** For a collection role, return a list of associations to be fetched by outerjoin */
  private void walkCollectionTree(
      final QueryableCollection persister,
      final String alias,
      final PropertyPath path,
      final int currentDepth)
      throws MappingException {

    if (persister.isOneToMany()) {
      walkEntityTree(
          (OuterJoinLoadable) persister.getElementPersister(), alias, path, currentDepth);
    } else {
      Type type = persister.getElementType();
      if (type.isAssociationType()) {
        // a many-to-many;
        // decrement currentDepth here to allow join across the association table
        // without exceeding MAX_FETCH_DEPTH (i.e. the "currentDepth - 1" bit)
        AssociationType associationType = (AssociationType) type;
        String[] aliasedLhsColumns = persister.getElementColumnNames(alias);
        String[] lhsColumns = persister.getElementColumnNames();
        // if the current depth is 0, the root thing being loaded is the
        // many-to-many collection itself.  Here, it is alright to use
        // an inner join...
        boolean useInnerJoin = currentDepth == 0;
        final JoinType joinType =
            getJoinType(
                associationType,
                persister.getFetchMode(),
                path,
                persister.getTableName(),
                lhsColumns,
                !useInnerJoin,
                currentDepth - 1,
                null // operations which cascade as far as the collection also cascade to collection
                     // elements
                );
        addAssociationToJoinTreeIfNecessary(
            associationType, aliasedLhsColumns, alias, path, currentDepth - 1, joinType);
      } else if (type.isComponentType()) {
        walkCompositeElementTree(
            (CompositeType) type,
            persister.getElementColumnNames(),
            persister,
            alias,
            path,
            currentDepth);
      }
    }
  }
  protected void initPropertyPaths(
      final String path,
      final Type type,
      String[] columns,
      final String[] formulaTemplates,
      final Mapping factory)
      throws MappingException {

    if (columns.length != type.getColumnSpan(factory)) {
      throw new MappingException("broken column mapping for: " + path + " of: " + getEntityName());
    }

    if (type.isAssociationType()) {
      AssociationType actype = (AssociationType) type;
      if (actype.useLHSPrimaryKey()) {
        columns = getIdentifierColumnNames();
      } else {
        String foreignKeyProperty = actype.getLHSPropertyName();
        if (foreignKeyProperty != null && !path.equals(foreignKeyProperty)) {
          // TODO: this requires that the collection is defined after the
          //      referenced property in the mapping file (ok?)
          columns = (String[]) columnsByPropertyPath.get(foreignKeyProperty);
          if (columns == null) return; // get em on the second pass!
        }
      }
    }

    if (path != null) addPropertyPath(path, type, columns, formulaTemplates);

    if (type.isComponentType()) {
      AbstractComponentType actype = (AbstractComponentType) type;
      initComponentPropertyPaths(path, actype, columns, formulaTemplates, factory);
      if (actype.isEmbedded()) {
        initComponentPropertyPaths(
            path == null ? null : StringHelper.qualifier(path),
            actype,
            columns,
            formulaTemplates,
            factory);
      }
    } else if (type.isEntityType()) {
      initIdentifierPropertyPaths(path, (EntityType) type, columns, factory);
    }
  }
Пример #10
0
 public CascadeStyle getCascadeStyle() throws MappingException {
   Type type = value.getType();
   if (type.isComponentType() && !type.isAnyType()) {
     AbstractComponentType actype = (AbstractComponentType) type;
     int length = actype.getSubtypes().length;
     for (int i = 0; i < length; i++) {
       if (actype.getCascadeStyle(i) != CascadeStyle.NONE) return CascadeStyle.ALL;
     }
     return CascadeStyle.NONE;
   } else if (cascade == null || cascade.equals("none")) {
     return CascadeStyle.NONE;
   } else {
     StringTokenizer tokens = new StringTokenizer(cascade, ", ");
     CascadeStyle[] styles = new CascadeStyle[tokens.countTokens()];
     int i = 0;
     while (tokens.hasMoreTokens()) {
       styles[i++] = CascadeStyle.getCascadeStyle(tokens.nextToken());
     }
     return new CascadeStyle.MultipleCascadeStyle(styles);
   }
 }
 private String getPathEntityName(String path) {
   Queryable persister = (Queryable) sessionFactory.getEntityPersister(rootEntityName);
   StringTokenizer tokens = new StringTokenizer(path, ".");
   String componentPath = "";
   while (tokens.hasMoreTokens()) {
     componentPath += tokens.nextToken();
     Type type = persister.toType(componentPath);
     if (type.isAssociationType()) {
       AssociationType atype = (AssociationType) type;
       persister =
           (Queryable)
               sessionFactory.getEntityPersister(atype.getAssociatedEntityName(sessionFactory));
       componentPath = "";
     } else if (type.isComponentType()) {
       componentPath += '.';
     } else {
       throw new QueryException("not an association: " + componentPath);
     }
   }
   return persister.getEntityName();
 }
  public void token(String token, QueryTranslatorImpl q) throws QueryException {

    if (token != null) path.append(token);

    String alias = q.getPathAlias(path.toString());
    if (alias != null) {
      reset(q); // reset the dotcount (but not the path)
      currentName = alias; // after reset!
      currentPropertyMapping = q.getPropertyMapping(currentName);
      if (!ignoreInitialJoin) {
        JoinSequence ojf = q.getPathJoin(path.toString());
        try {
          joinSequence.addCondition(
              ojf.toJoinFragment(q.getEnabledFilters(), true)
                  .toWhereFragmentString()); // after reset!
        } catch (MappingException me) {
          throw new QueryException(me);
        }
        // we don't need to worry about any condition in the ON clause
        // here (toFromFragmentString), since anything in the ON condition
        // is already applied to the whole query
      }
    } else if (".".equals(token)) {
      dotcount++;
    } else {
      if (dotcount == 0) {
        if (!continuation) {
          if (!q.isName(token)) throw new QueryException("undefined alias: " + token);
          currentName = token;
          currentPropertyMapping = q.getPropertyMapping(currentName);
        }
      } else if (dotcount == 1) {
        if (currentName != null) {
          currentProperty = token;
        } else if (collectionName != null) {
          // processCollectionProperty(token, q.getCollectionPersister(collectionRole),
          // collectionName);
          continuation = false;
        } else {
          throw new QueryException("unexpected");
        }
      } else { // dotcount>=2

        // Do the corresponding RHS
        Type propertyType = getPropertyType();

        if (propertyType == null) {
          throw new QueryException("unresolved property: " + path);
        }

        if (propertyType.isComponentType()) {
          dereferenceComponent(token);
        } else if (propertyType.isEntityType()) {
          if (!isCollectionValued()) dereferenceEntity(token, (EntityType) propertyType, q);
        } else if (propertyType.isCollectionType()) {
          dereferenceCollection(token, ((CollectionType) propertyType).getRole(), q);

        } else {
          if (token != null) throw new QueryException("dereferenced: " + path);
        }
      }
    }
  }