@Override public void initialize(Serializable id, SessionImplementor session) throws HibernateException { if (log.isDebugEnabled()) { log.debugf( "Loading collection: %s", MessageHelper.collectionInfoString(collectionPersister, id, getFactory())); } final Serializable[] ids = new Serializable[] {id}; try { final QueryParameters qp = new QueryParameters(); qp.setPositionalParameterTypes(new Type[] {collectionPersister.getKeyType()}); qp.setPositionalParameterValues(ids); qp.setCollectionKeys(ids); executeLoad(session, qp, staticLoadQuery, true, null); } catch (SQLException sqle) { throw getFactory() .getSQLExceptionHelper() .convert( sqle, "could not initialize a collection: " + MessageHelper.collectionInfoString(collectionPersister, id, getFactory()), staticLoadQuery.getSqlStatement()); } log.debug("Done loading collection"); }
/** * 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 static void processDereferencedCollection( PersistentCollection coll, SessionImplementor session) { final PersistenceContext persistenceContext = session.getPersistenceContext(); CollectionEntry entry = persistenceContext.getCollectionEntry(coll); final CollectionPersister loadedPersister = entry.getLoadedPersister(); if (LOG.isDebugEnabled() && loadedPersister != null) { LOG.debugf( "Collection dereferenced: %s", MessageHelper.collectionInfoString( loadedPersister, entry.getLoadedKey(), session.getFactory())); } // do a check boolean hasOrphanDelete = loadedPersister != null && loadedPersister.hasOrphanDelete(); if (hasOrphanDelete) { Serializable ownerId = loadedPersister.getOwnerEntityPersister().getIdentifier(coll.getOwner(), session); if (ownerId == null) { // the owning entity may have been deleted and its identifier unset due to // identifier-rollback; in which case, try to look up its identifier from // the persistence context if (session.getFactory().getSettings().isIdentifierRollbackEnabled()) { EntityEntry ownerEntry = persistenceContext.getEntry(coll.getOwner()); if (ownerEntry != null) { ownerId = ownerEntry.getId(); } } if (ownerId == null) { throw new AssertionFailure( "Unable to determine collection owner identifier for orphan-delete processing"); } } EntityKey key = session.generateEntityKey(ownerId, loadedPersister.getOwnerEntityPersister()); Object owner = persistenceContext.getEntity(key); if (owner == null) { throw new AssertionFailure( "collection owner not associated with session: " + loadedPersister.getRole()); } EntityEntry e = persistenceContext.getEntry(owner); // only collections belonging to deleted entities are allowed to be dereferenced in the case // of orphan delete if (e != null && e.getStatus() != Status.DELETED && e.getStatus() != Status.GONE) { throw new HibernateException( "A collection with cascade=\"all-delete-orphan\" was no longer referenced by the owning entity instance: " + loadedPersister.getRole()); } } // do the work entry.setCurrentPersister(null); entry.setCurrentKey(null); prepareCollectionForUpdate(coll, entry, session.getFactory()); }
public void evictCollection(String role, Serializable ownerIdentifier) { CollectionPersister p = getCollectionPersister(role); if (p.hasCache()) { if (log.isDebugEnabled()) { log.debug( "evicting second-level cache: " + MessageHelper.collectionInfoString( p, ownerIdentifier, SessionFactoryImpl.this)); } CacheKey cacheKey = buildCacheKey(ownerIdentifier, p); p.getCacheAccessStrategy().evict(cacheKey); } }
private static void processNeverReferencedCollection( PersistentCollection coll, SessionImplementor session) throws HibernateException { final PersistenceContext persistenceContext = session.getPersistenceContext(); CollectionEntry entry = persistenceContext.getCollectionEntry(coll); if (LOG.isDebugEnabled()) { LOG.debugf( "Found collection with unloaded owner: %s", MessageHelper.collectionInfoString( entry.getLoadedPersister(), entry.getLoadedKey(), session.getFactory())); } entry.setCurrentPersister(entry.getLoadedPersister()); entry.setCurrentKey(entry.getLoadedKey()); prepareCollectionForUpdate(coll, entry, session.getFactory()); }
private void evictCollection(PersistentCollection collection) { CollectionEntry ce = (CollectionEntry) getSession().getPersistenceContext().getCollectionEntries().remove(collection); if (log.isDebugEnabled()) log.debug( "evicting collection: " + MessageHelper.collectionInfoString( ce.getLoadedPersister(), ce.getLoadedKey(), getSession().getFactory())); if (ce.getLoadedPersister() != null && ce.getLoadedKey() != null) { // TODO: is this 100% correct? getSession() .getPersistenceContext() .getCollectionsByKey() .remove( new CollectionKey( ce.getLoadedPersister(), ce.getLoadedKey(), getSession().getEntityMode())); } }
protected int doUpdateRows( Serializable id, PersistentCollection collection, SessionImplementor session) throws HibernateException { if (ArrayHelper.isAllFalse(elementColumnIsSettable)) return 0; try { PreparedStatement st = null; boolean callable = isUpdateCallable(); Iterator entries = collection.entries(this); try { int i = 0; int count = 0; while (entries.hasNext()) { int offset = 1; Object entry = entries.next(); if (collection.needsUpdating(entry, i, elementType)) { if (st == null) { if (callable) { CallableStatement callstatement = session.getBatcher().prepareBatchCallableStatement(getSQLUpdateRowString()); callstatement.registerOutParameter( offset++, Types .NUMERIC); // TODO: should we require users to return number of update rows // ? (we cant make it return this without changing // collectionpersister interface) st = callstatement; } else { st = session.getBatcher().prepareBatchStatement(getSQLUpdateRowString()); } } int loc = writeElement(st, collection.getElement(entry), offset, session); if (hasIdentifier) { loc = writeIdentifier(st, collection.getIdentifier(entry, i), loc, session); } else { loc = writeKey(st, id, loc, session); if (hasIndex && !indexContainsFormula) { loc = writeIndexToWhere(st, collection.getIndex(entry, i, this), loc, session); } else { loc = writeElementToWhere(st, collection.getSnapshotElement(entry, i), loc, session); } } session.getBatcher().addToBatch(1); count++; } i++; } return count; } catch (SQLException sqle) { session.getBatcher().abortBatch(sqle); throw sqle; } } catch (SQLException sqle) { throw JDBCExceptionHelper.convert( getSQLExceptionConverter(), sqle, "could not update collection rows: " + MessageHelper.collectionInfoString(this, id, getFactory()), getSQLUpdateRowString()); } }
public String toString() { return "CollectionKey" + MessageHelper.collectionInfoString(factory.getCollectionPersister(role), key, factory); }
protected int doUpdateRows( Serializable id, PersistentCollection collection, SessionImplementor session) throws HibernateException { // we finish all the "removes" first to take care of possible unique // constraints and so that we can take better advantage of batching try { int count = 0; if (isRowDeleteEnabled()) { boolean useBatch = true; PreparedStatement st = null; // update removed rows fks to null try { int i = 0; Iterator entries = collection.entries(this); int offset = 1; Expectation expectation = Expectations.NONE; while (entries.hasNext()) { Object entry = entries.next(); if (collection.needsUpdating( entry, i, elementType)) { // will still be issued when it used to be null if (st == null) { String sql = getSQLDeleteRowString(); if (isDeleteCallable()) { expectation = Expectations.appropriateExpectation(getDeleteCheckStyle()); useBatch = expectation.canBeBatched(); st = useBatch ? session.getBatcher().prepareBatchCallableStatement(sql) : session.getBatcher().prepareCallableStatement(sql); offset += expectation.prepare(st); } else { st = session.getBatcher().prepareBatchStatement(getSQLDeleteRowString()); } } int loc = writeKey(st, id, offset, session); writeElementToWhere(st, collection.getSnapshotElement(entry, i), loc, session); if (useBatch) { session.getBatcher().addToBatch(expectation); } else { expectation.verifyOutcome(st.executeUpdate(), st, -1); } count++; } i++; } } catch (SQLException sqle) { if (useBatch) { session.getBatcher().abortBatch(sqle); } throw sqle; } finally { if (!useBatch) { session.getBatcher().closeStatement(st); } } } if (isRowInsertEnabled()) { Expectation expectation = Expectations.appropriateExpectation(getInsertCheckStyle()); boolean callable = isInsertCallable(); boolean useBatch = expectation.canBeBatched(); String sql = getSQLInsertRowString(); PreparedStatement st = null; // now update all changed or added rows fks try { int i = 0; Iterator entries = collection.entries(this); while (entries.hasNext()) { Object entry = entries.next(); int offset = 1; if (collection.needsUpdating(entry, i, elementType)) { if (useBatch) { if (st == null) { if (callable) { st = session.getBatcher().prepareBatchCallableStatement(sql); } else { st = session.getBatcher().prepareBatchStatement(sql); } } } else { if (callable) { st = session.getBatcher().prepareCallableStatement(sql); } else { st = session.getBatcher().prepareStatement(sql); } } offset += expectation.prepare(st); int loc = writeKey(st, id, offset, session); if (hasIndex && !indexContainsFormula) { loc = writeIndexToWhere(st, collection.getIndex(entry, i, this), loc, session); } writeElementToWhere(st, collection.getElement(entry), loc, session); if (useBatch) { session.getBatcher().addToBatch(expectation); } else { expectation.verifyOutcome(st.executeUpdate(), st, -1); } count++; } i++; } } catch (SQLException sqle) { if (useBatch) { session.getBatcher().abortBatch(sqle); } throw sqle; } finally { if (!useBatch) { session.getBatcher().closeStatement(st); } } } return count; } catch (SQLException sqle) { throw getFactory() .getSQLExceptionHelper() .convert( sqle, "could not update collection rows: " + MessageHelper.collectionInfoString(this, id, getFactory()), getSQLInsertRowString()); } }