/** * For a component, add to a list of associations to be fetched by outerjoin * * @param componentType The component type to be walked. * @param propertyNumber The property number for the component property (relative to persister). * @param begin todo unknowm * @param persister The owner of the component property * @param alias The root alias * @param path The property access path * @param currentDepth The current join depth * @throws org.hibernate.MappingException ??? */ private void walkComponentTree( final CompositeType componentType, final int propertyNumber, int begin, final OuterJoinLoadable persister, final String alias, final PropertyPath path, final int currentDepth) throws MappingException { Type[] types = componentType.getSubtypes(); String[] propertyNames = componentType.getPropertyNames(); for (int i = 0; i < types.length; i++) { if (types[i].isAssociationType()) { AssociationType associationType = (AssociationType) types[i]; String[] aliasedLhsColumns = JoinHelper.getAliasedLHSColumnNames( associationType, alias, propertyNumber, begin, persister, getFactory()); String[] lhsColumns = JoinHelper.getLHSColumnNames( associationType, propertyNumber, begin, persister, getFactory()); String lhsTable = JoinHelper.getLHSTableName(associationType, propertyNumber, persister); final PropertyPath subPath = path.append(propertyNames[i]); final boolean[] propertyNullability = componentType.getPropertyNullability(); final JoinType joinType = getJoinType( persister, subPath, propertyNumber, associationType, componentType.getFetchMode(i), componentType.getCascadeStyle(i), lhsTable, lhsColumns, propertyNullability == null || propertyNullability[i], currentDepth); addAssociationToJoinTreeIfNecessary( associationType, aliasedLhsColumns, alias, subPath, currentDepth, joinType); } else if (types[i].isComponentType()) { final PropertyPath subPath = path.append(propertyNames[i]); walkComponentTree( (CompositeType) types[i], propertyNumber, begin, persister, alias, subPath, currentDepth); } begin += types[i].getColumnSpan(getFactory()); } }
/** * 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); } } } }
/** For a composite element, add to a list of associations to be fetched by outerjoin */ private void walkCompositeElementTree( final CompositeType compositeType, final String[] cols, final QueryableCollection persister, final String alias, final PropertyPath path, final int currentDepth) throws MappingException { Type[] types = compositeType.getSubtypes(); String[] propertyNames = compositeType.getPropertyNames(); int begin = 0; for (int i = 0; i < types.length; i++) { int length = types[i].getColumnSpan(getFactory()); String[] lhsColumns = ArrayHelper.slice(cols, begin, length); if (types[i].isAssociationType()) { AssociationType associationType = (AssociationType) types[i]; // simple, because we can't have a one-to-one or a collection // (or even a property-ref) in a composite-element: String[] aliasedLhsColumns = StringHelper.qualify(alias, lhsColumns); final PropertyPath subPath = path.append(propertyNames[i]); final boolean[] propertyNullability = compositeType.getPropertyNullability(); final JoinType joinType = getJoinType( associationType, compositeType.getFetchMode(i), subPath, persister.getTableName(), lhsColumns, propertyNullability == null || propertyNullability[i], currentDepth, compositeType.getCascadeStyle(i)); addAssociationToJoinTreeIfNecessary( associationType, aliasedLhsColumns, alias, subPath, currentDepth, joinType); } else if (types[i].isComponentType()) { final PropertyPath subPath = path.append(propertyNames[i]); walkCompositeElementTree( (CompositeType) types[i], lhsColumns, persister, alias, subPath, currentDepth); } begin += length; } }
public CascadeStyle getCascadeStyle() throws MappingException { Type type = value.getType(); if (type.isComponentType() && !type.isAnyType()) { CompositeType actype = (CompositeType) 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); } }