@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");
  }
Пример #2
0
  /**
   * 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);
  }
Пример #3
0
  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);
   }
 }
Пример #5
0
  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());
  }
Пример #6
0
 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);
 }
Пример #9
0
  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());
    }
  }