FromElement createElementJoin(QueryableCollection queryableCollection) throws SemanticException { FromElement elem; implied = true; // TODO: always true for now, but not if we later decide to support elements() in the // from clause inElementsFunction = true; Type elementType = queryableCollection.getElementType(); if (!elementType.isEntityType()) { throw new IllegalArgumentException( "Cannot create element join for a collection of non-entities!"); } this.queryableCollection = queryableCollection; SessionFactoryHelper sfh = fromClause.getSessionFactoryHelper(); FromElement destination = null; String tableAlias = null; EntityPersister entityPersister = queryableCollection.getElementPersister(); tableAlias = fromClause.getAliasGenerator().createName(entityPersister.getEntityName()); String associatedEntityName = entityPersister.getEntityName(); EntityPersister targetEntityPersister = sfh.requireClassPersister(associatedEntityName); // Create the FROM element for the target (the elements of the collection). destination = createAndAddFromElement( associatedEntityName, classAlias, targetEntityPersister, (EntityType) queryableCollection.getElementType(), tableAlias); // If the join is implied, then don't include sub-classes on the element. if (implied) { destination.setIncludeSubclasses(false); } fromClause.addCollectionJoinFromElementByPath(path, destination); // origin.addDestination(destination); // Add the query spaces. fromClause.getWalker().addQuerySpaces(entityPersister.getQuerySpaces()); CollectionType type = queryableCollection.getCollectionType(); String role = type.getRole(); String roleAlias = origin.getTableAlias(); String[] targetColumns = sfh.getCollectionElementColumns(role, roleAlias); AssociationType elementAssociationType = sfh.getElementAssociationType(type); // Create the join element under the from element. int joinType = JoinFragment.INNER_JOIN; JoinSequence joinSequence = sfh.createJoinSequence( implied, elementAssociationType, tableAlias, joinType, targetColumns); elem = initializeJoin(path, destination, joinSequence, targetColumns, origin, false); elem.setUseFromFragment( true); // The associated entity is implied, but it must be included in the FROM. elem.setCollectionTableAlias(roleAlias); // The collection alias is the role. return elem; }
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; }
/** * Initialize the role of the collection. * * @param collection The collection to be updated by reachability. * @param type The type of the collection. * @param entity The owner of the collection. * @param session The session from which this request originates */ public static void processReachableCollection( PersistentCollection collection, CollectionType type, Object entity, SessionImplementor session) { collection.setOwner(entity); CollectionEntry ce = session.getPersistenceContext().getCollectionEntry(collection); if (ce == null) { // refer to comment in StatefulPersistenceContext.addCollection() throw new HibernateException( "Found two representations of same collection: " + type.getRole()); } // The CollectionEntry.isReached() stuff is just to detect any silly users // who set up circular or shared references between/to collections. if (ce.isReached()) { // We've been here before throw new HibernateException("Found shared references to a collection: " + type.getRole()); } ce.setReached(true); SessionFactoryImplementor factory = session.getFactory(); CollectionPersister persister = factory.getCollectionPersister(type.getRole()); ce.setCurrentPersister(persister); ce.setCurrentKey( type.getKeyOfOwner(entity, session)); // TODO: better to pass the id in as an argument? if (LOG.isDebugEnabled()) { if (collection.wasInitialized()) LOG.debugf( "Collection found: %s, was: %s (initialized)", MessageHelper.collectionInfoString(persister, ce.getCurrentKey(), factory), MessageHelper.collectionInfoString( ce.getLoadedPersister(), ce.getLoadedKey(), factory)); else LOG.debugf( "Collection found: %s, was: %s (uninitialized)", MessageHelper.collectionInfoString(persister, ce.getCurrentKey(), factory), MessageHelper.collectionInfoString( ce.getLoadedPersister(), ce.getLoadedKey(), factory)); } prepareCollectionForUpdate(collection, ce, factory); }
private boolean isCollectionMatching(CollectionType type, String primarySideTableName) { // Find the reverse side collection and check if the table name and key columns are matching // what we have on the main side String collectionRole = type.getRole(); CollectionPhysicalModel reverseCollectionPersister = (CollectionPhysicalModel) session.getFactory().getCollectionPersister(collectionRole); boolean isSameTable = primarySideTableName.equals(reverseCollectionPersister.getTableName()); return isSameTable && Arrays.equals(keyColumnNames, reverseCollectionPersister.getKeyColumnNames()); }
/** * Iterate just the elements of the collection that are already there. Don't load any new elements * from the database. */ public static Iterator getLoadedElementsIterator( SessionImplementor session, CollectionType collectionType, Object collection) { if (collectionIsInitialized(collection)) { // handles arrays and newly instantiated collections return collectionType.getElementsIterator(collection, session); } else { // does not handle arrays (thats ok, cos they can't be lazy) // or newly instantiated collections, so we can do the cast return ((PersistentCollection) collection).queuedAdditionIterator(); } }
/** * For each of the fields contained in this {@link Locks} object, parse out the type and the * field name and store those as the key and value in the "value" argument. */ public void fillRelationships(SessionFactoryImplementor sfi, Map<String, Relationship> value) { final Type[] types = cm.getPropertyTypes(); for (int t = 0; t < types.length; t++) { final Type type = types[t]; final String name = type.getName(); String to = null; Relationship field = null; if (type instanceof EntityType) { final EntityType entType = (EntityType) type; to = entType.getAssociatedEntityName(); field = new Relationship(cm.getPropertyNames()[t], false); } else if (types[t] instanceof CollectionType) { final CollectionType colType = (CollectionType) types[t]; final Type elemType = colType.getElementType(sfi); if (!elemType.isEntityType()) { continue; // The case for count maps and other primitives. } to = elemType.getName(); int open = name.indexOf("("); int close = name.lastIndexOf(")"); String role = name.substring(open + 1, close); int dot = role.lastIndexOf("."); field = new Relationship(role.substring(dot + 1), true); } if (to != null && field != null) { Map<String, ClassMetadata> m = sfi.getAllClassMetadata(); for (Class<?> c : Impl.hierarchy(m, to)) { value.put(c.getName(), field); } } } }
public void evictCollection(Object value, CollectionType type) { final Object pc; if (type.hasHolder(getSession().getEntityMode())) { pc = getSession().getPersistenceContext().removeCollectionHolder(value); } else if (value instanceof PersistentCollection) { pc = value; } else { return; // EARLY EXIT! } PersistentCollection collection = (PersistentCollection) pc; if (collection.unsetSession(getSession())) evictCollection(collection); }
Object processCollection(Object collection, CollectionType type) throws HibernateException { if (collection == CollectionType.UNFETCHED_COLLECTION) { return null; } if (collection != null) { final PersistentCollection coll; if (type.hasHolder()) { coll = getSession().getPersistenceContext().getCollectionHolder(collection); } else { coll = (PersistentCollection) collection; } Collections.processReachableCollection(coll, type, owner, getSession()); } return null; }
/** * Given a collection, get an iterator of all its children, loading them from the database if * necessary. * * @param session The session within which the cascade is occuring. * @param collectionType The mapping type of the collection. * @param collection The collection instance. * @return The children iterator. */ private static Iterator getAllElementsIterator( EventSource session, CollectionType collectionType, Object collection) { return collectionType.getElementsIterator(collection, session); }