/**
   * INTERNAL: Return the value of the field from the row or a value holder on the query to obtain
   * the object. Check for batch + aggregation reading.
   */
  public Object valueFromRow(
      AbstractRecord row,
      JoinedAttributeManager joinManager,
      ObjectBuildingQuery query,
      AbstractSession executionSession)
      throws DatabaseException {
    Ref ref = (Ref) row.get(getField());

    if (ref == null) {
      return null;
    }

    Struct struct;
    try {
      ((DatabaseAccessor) executionSession.getAccessor()).incrementCallCount(executionSession);
      java.sql.Connection connection =
          ((DatabaseAccessor) executionSession.getAccessor()).getConnection();
      struct =
          (Struct) executionSession.getPlatform().getRefValue(ref, executionSession, connection);
    } catch (java.sql.SQLException exception) {
      throw DatabaseException.sqlException(exception, executionSession, false);
    }
    AbstractRecord targetRow =
        ((ObjectRelationalDataTypeDescriptor) getReferenceDescriptor())
            .buildRowFromStructure(struct);
    ((DatabaseAccessor) executionSession.getAccessor()).decrementCallCount();

    return getReferenceDescriptor().getObjectBuilder().buildObject(query, targetRow, joinManager);
  }
  /** INTERNAL: Get a value from the object and set that in the respective field of the row. */
  @Override
  public Object valueFromObject(Object object, DatabaseField field, AbstractSession session) {
    // First check if the value can be obtained from the value holder's row.
    AbstractRecord referenceRow =
        getIndirectionPolicy().extractReferenceRow(getAttributeValueFromObject(object));
    if (referenceRow != null) {
      Object value = referenceRow.get(field);

      // Must ensure the classification to get a cache hit.
      try {
        value = session.getDatasourcePlatform().convertObject(value, getFieldClassification(field));
      } catch (ConversionException e) {
        throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
      }

      return value;
    }

    // 2.5.1.6 PWK.  added to support batch reading on variable one to ones
    Object referenceObject = getRealAttributeValueFromObject(object, session);
    String queryKeyName = (String) getSourceToTargetQueryKeyNames().get(field);
    ClassDescriptor objectDescriptor = session.getDescriptor(referenceObject.getClass());
    DatabaseField targetField =
        objectDescriptor.getObjectBuilder().getTargetFieldForQueryKeyName(queryKeyName);

    if (targetField == null) {
      return null;
    }

    return objectDescriptor
        .getObjectBuilder()
        .extractValueFromObjectForField(referenceObject, targetField, session);
  }
  /**
   * PUBLIC: Return a session broker that behaves as a client session broker. An acquire session
   * broker is done under the covers on each session inside the session broker, and a new broker is
   * returned.
   *
   * <p>NOTE: when finished with the client broker, it should be releases. See
   * releaseClientSessionBroker.
   */
  public SessionBroker acquireClientSessionBroker() {
    log(SessionLog.FINER, SessionLog.CONNECTION, "acquire_client_session_broker");
    SessionBroker clientBroker = copySessionBroker();
    clientBroker.parent = this;
    clientBroker
        .getIdentityMapAccessorInstance()
        .setIdentityMapManager(getIdentityMapAccessorInstance().getIdentityMapManager());
    clientBroker.commitManager = getCommitManager();
    clientBroker.commandManager = getCommandManager();
    clientBroker.externalTransactionController = getExternalTransactionController();
    clientBroker.setServerPlatform(getServerPlatform());
    String sessionName;
    AbstractSession serverSession;
    Iterator names = this.getSessionsByName().keySet().iterator();
    while (names.hasNext()) {
      sessionName = (String) names.next();
      serverSession = getSessionForName(sessionName);
      if (serverSession instanceof org.eclipse.persistence.sessions.server.ServerSession) {
        if (serverSession.getProject().hasIsolatedClasses()) {
          throw ValidationException.isolatedDataNotSupportedInSessionBroker(sessionName);
        }
        clientBroker.internalRegisterSession(
            sessionName,
            ((org.eclipse.persistence.sessions.server.ServerSession) serverSession)
                .acquireClientSession());
      } else {
        throw ValidationException.cannotAcquireClientSessionFromSession();
      }
    }

    clientBroker.initializeSequencing();
    return clientBroker;
  }
  /** Delete all of the objects with the matching class. */
  public void deleteAllObjects(Class theClass, List objects, AbstractSession session) {
    ClassDescriptor descriptor = null;

    if (((UnitOfWorkImpl) session).shouldOrderUpdates()) { // bug 331064 - Sort the delete order
      objects = sort(theClass, objects);
    }

    int size = objects.size();
    for (int index = 0; index < size; index++) {
      Object objectToDelete = objects.get(index);
      if (objectToDelete.getClass() == theClass) {
        if (descriptor == null) {
          descriptor = session.getDescriptor(theClass);
        }
        // PERF: Get the descriptor query, to avoid extra query creation.
        DeleteObjectQuery deleteQuery = descriptor.getQueryManager().getDeleteQuery();
        if (deleteQuery == null) {
          deleteQuery = new DeleteObjectQuery();
          deleteQuery.setDescriptor(descriptor);
        } else {
          // Ensure original query has been prepared.
          deleteQuery.checkPrepare(session, deleteQuery.getTranslationRow());
          deleteQuery = (DeleteObjectQuery) deleteQuery.clone();
        }
        deleteQuery.setIsExecutionClone(true);
        deleteQuery.setObject(objectToDelete);
        session.executeQuery(deleteQuery);
      }
    }
  }
  /**
   * delete all of the objects as a single transaction. This should delete the object in the correct
   * order to maintain referential integrity.
   */
  public void deleteAllObjects(List objects)
      throws RuntimeException, DatabaseException, OptimisticLockException {
    this.isActive = true;
    AbstractSession session = getSession();
    session.beginTransaction();

    try {
      // PERF: Optimize single object case.
      if (objects.size() == 1) {
        deleteAllObjects(objects.get(0).getClass(), objects, session);
      } else {
        List commitOrder = getCommitOrder();
        for (int orderIndex = commitOrder.size() - 1; orderIndex >= 0; orderIndex--) {
          Class theClass = (Class) commitOrder.get(orderIndex);
          deleteAllObjects(theClass, objects, session);
        }
      }

      session.commitTransaction();
    } catch (RuntimeException exception) {
      try {
        session.rollbackTransaction();
      } catch (Exception ignore) {
      }
      throw exception;
    } finally {
      reinitialize();
      this.isActive = false;
    }
  }
  /**
   * INTERNAL: Return the results from exeucting the database query. the arguments should be a
   * database row with raw data values. Find the correct child session to broker the query to, and
   * return the result of the session executing the query.
   */
  public Object internalExecuteQuery(DatabaseQuery query, AbstractRecord row)
      throws DatabaseException, QueryException {
    AbstractSession sessionByQuery = getSessionForQuery(query);

    // Note, this disables local profilers.
    return sessionByQuery.internalExecuteQuery(query, row);
  }
 /**
  * Commit all of the objects of the class type in the change set. This allows for the order of the
  * classes to be processed optimally.
  */
 protected void commitNewObjectsForClassWithChangeSet(
     UnitOfWorkChangeSet uowChangeSet, Class theClass) {
   Map<ObjectChangeSet, ObjectChangeSet> newObjectChangesList =
       uowChangeSet.getNewObjectChangeSets().get(theClass);
   if (newObjectChangesList != null) { // may be no changes for that class type.
     AbstractSession session = getSession();
     ClassDescriptor descriptor = session.getDescriptor(theClass);
     List<ObjectChangeSet> newChangeSets = new ArrayList(newObjectChangesList.values());
     int size = newChangeSets.size();
     for (int index = 0; index < size; index++) {
       ObjectChangeSet changeSetToWrite = newChangeSets.get(index);
       Object objectToWrite = changeSetToWrite.getUnitOfWorkClone();
       if (!isProcessedCommit(objectToWrite)) {
         // PERF: Get the descriptor query, to avoid extra query creation.
         InsertObjectQuery commitQuery = descriptor.getQueryManager().getInsertQuery();
         if (commitQuery == null) {
           commitQuery = new InsertObjectQuery();
           commitQuery.setDescriptor(descriptor);
         } else {
           // Ensure original query has been prepared.
           commitQuery.checkPrepare(session, commitQuery.getTranslationRow());
           commitQuery = (InsertObjectQuery) commitQuery.clone();
         }
         commitQuery.setIsExecutionClone(true);
         commitQuery.setObjectChangeSet(changeSetToWrite);
         commitQuery.setObject(objectToWrite);
         commitQuery.cascadeOnlyDependentParts();
         commitQuery.setModifyRow(null);
         session.executeQuery(commitQuery);
       }
       uowChangeSet.putNewObjectInChangesList(changeSetToWrite, session);
     }
   }
 }
  /**
   * PUBLIC: set the integrityChecker. IntegrityChecker holds all the ClassDescriptor Exceptions.
   */
  public void setIntegrityChecker(IntegrityChecker integrityChecker) {
    super.setIntegrityChecker(integrityChecker);

    for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
      AbstractSession session = (AbstractSession) sessionEnum.next();
      session.setIntegrityChecker(integrityChecker);
    }
  }
  /**
   * PUBLIC: Set the message log.
   *
   * @see #logMessages()
   */
  public void setLog(Writer log) {
    super.setLog(log);

    for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
      AbstractSession session = (AbstractSession) sessionEnum.next();
      session.setLog(log);
    }
  }
  /**
   * PUBLIC: Set the profiler for the session. This allows for performance operations to be
   * profiled.
   */
  public void setProfiler(SessionProfiler profiler) {
    super.setProfiler(profiler);

    for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
      AbstractSession session = (AbstractSession) sessionEnum.next();
      session.setProfiler(profiler);
    }
  }
  /** PUBLIC: Return if this session is a server session broker. */
  public boolean isServerSessionBroker() {
    for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
      AbstractSession session = (AbstractSession) sessionEnum.next();
      if (session.isServerSession()) {
        return true;
      }
    }

    return false;
  }
 /**
  * PUBLIC: Release the session. This does nothing by default, but allows for other sessions such
  * as the ClientSession to do something.
  */
 public void release() {
   if (isClientSessionBroker()) {
     log(SessionLog.FINER, SessionLog.CONNECTION, "releasing_client_session_broker");
   }
   AbstractSession session;
   for (Iterator enumtr = getSessionsByName().values().iterator(); enumtr.hasNext(); ) {
     session = (AbstractSession) enumtr.next();
     session.release();
   }
   super.release();
 }
 /**
  * INTERNAL: This method notifies the accessor that a particular sets of writes has completed.
  * This notification can be used for such thing as flushing the batch mechanism
  */
 public void writesCompleted() {
   for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
     AbstractSession session = (AbstractSession) sessionEnum.next();
     if (!session.isConnected()) {
       throw DatabaseException.databaseAccessorNotConnected();
     }
   }
   for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
     AbstractSession session = (AbstractSession) sessionEnum.next();
     session.writesCompleted();
   }
 }
 /**
  * INTERNAL: Commit the transaction on all child sessions. This assumes that the commit of the
  * transaction will not fail because all of the modification has already taken place and no errors
  * would have occurred.
  */
 protected void basicCommitTransaction() throws DatabaseException {
   // Do one last check it make sure that all sessions are still connected.
   for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
     AbstractSession session = (AbstractSession) sessionEnum.next();
     if (!session.isConnected()) {
       throw DatabaseException.databaseAccessorNotConnected();
     }
   }
   for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
     AbstractSession session = (AbstractSession) sessionEnum.next();
     session.commitTransaction();
   }
 }
  /** PUBLIC: Return if all sessions are still connected to the database. */
  public boolean isConnected() {
    if ((getSessionsByName() == null) || (getSessionsByName().isEmpty())) {
      return false;
    }

    for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
      AbstractSession session = (AbstractSession) sessionEnum.next();
      if (!session.isConnected()) {
        return false;
      }
    }

    return true;
  }
 /** INTERNAL: Rollback the transaction on all child sessions. */
 protected void basicRollbackTransaction() throws DatabaseException {
   DatabaseException globalException = null;
   for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
     AbstractSession session = (AbstractSession) sessionEnum.next();
     try {
       session.rollbackTransaction();
     } catch (DatabaseException exception) {
       globalException = exception;
     }
   }
   if (globalException != null) {
     throw globalException;
   }
 }
  /**
   * INTERNAL: Register the session under its name. All of the session's descriptors must have
   * already been registered. The session should not be connected and descriptors should not be
   * initialized. Used for client session broker
   */
  public void internalRegisterSession(String name, AbstractSession session) {
    // Bug#3911318  Removed session brokers and sessions point to the same descriptors.
    // They don't need to be reassigned.  Also the code to add read only classes has been removed
    // because client broker and server broker point to the same project.
    session.setIsInBroker(true);
    getSessionsByName().put(name, session);
    session.setBroker(this);
    session.setName(name);

    /*       // The keys/classes must also be used as some descriptors may be under multiple classes.
          Iterator classes = session.getDescriptors().keySet().iterator();
          while (classes.hasNext()) {
              Class descriptorClass = (Class)classes.next();
              getSessionNamesByClass().put(descriptorClass, session);
          }
    */ }
  /**
   * PUBLIC: Register the session under its name. All of the session's descriptors must have already
   * been registered. The session should not be connected and descriptors should not be initialized.
   */
  public void registerSession(String name, AbstractSession session) {
    session.setIsInBroker(true);
    getSessionsByName().put(name, session);
    session.setBroker(this);
    session.setName(name);

    // The keys/classes must also be used as some descriptors may be under multiple classes.
    Iterator descriptors = session.getDescriptors().values().iterator();
    Iterator classes = session.getDescriptors().keySet().iterator();
    while (descriptors.hasNext()) {
      ClassDescriptor descriptor = (ClassDescriptor) descriptors.next();
      Class descriptorClass = (Class) classes.next();
      getSessionNamesByClass().put(descriptorClass, name);
      getDescriptors().put(descriptorClass, descriptor);
    }
  }
  /**
   * INTERNAL: Compare the references of the two objects are the same, not the objects themselves.
   * Used for independent relationships. This is used for testing and validation purposes.
   *
   * <p>Must get separate fields for the objects because we may be adding a different class to the
   * attribute because of the interface
   */
  @Override
  protected boolean compareObjectsWithoutPrivateOwned(
      Object firstObject, Object secondObject, AbstractSession session) {
    Object firstPrivateObject = getRealAttributeValueFromObject(firstObject, session);
    Object secondPrivateObject = getRealAttributeValueFromObject(secondObject, session);

    if ((firstPrivateObject == null) && (secondPrivateObject == null)) {
      return true;
    }

    if ((firstPrivateObject == null) || (secondPrivateObject == null)) {
      return false;
    }
    if (firstPrivateObject.getClass() != secondPrivateObject.getClass()) {
      return false;
    }
    Iterator targetKeys = getSourceToTargetQueryKeyNames().values().iterator();
    ClassDescriptor descriptor = session.getDescriptor(firstPrivateObject.getClass());
    ClassDescriptor descriptor2 = session.getDescriptor(secondPrivateObject.getClass());

    while (targetKeys.hasNext()) {
      String queryKey = (String) targetKeys.next();
      DatabaseField field = descriptor.getObjectBuilder().getFieldForQueryKeyName(queryKey);
      Object firstObjectField =
          descriptor
              .getObjectBuilder()
              .extractValueFromObjectForField(firstPrivateObject, field, session);
      DatabaseField field2 = descriptor2.getObjectBuilder().getFieldForQueryKeyName(queryKey);
      Object secondObjectField =
          descriptor2
              .getObjectBuilder()
              .extractValueFromObjectForField(secondPrivateObject, field2, session);

      if (!((firstObjectField == null) && (secondObjectField == null))) {
        if ((firstObjectField == null) || (secondObjectField == null)) {
          return false;
        }
        if (!firstObjectField.equals(secondObjectField)) {
          return false;
        }
      }
    }

    return true;
  }
  /** INTERNAL: Acquires a special historical session for reading objects as of a past time. */
  public org.eclipse.persistence.sessions.Session acquireHistoricalSession(AsOfClause clause)
      throws ValidationException {
    if (isServerSessionBroker()) {
      throw ValidationException.cannotAcquireHistoricalSession();
    }

    // ? logMessage("acquire_client_session_broker", (Object[])null);
    SessionBroker historicalBroker = copySessionBroker();
    String sessionName;
    AbstractSession session;
    Iterator names = this.getSessionsByName().keySet().iterator();
    while (names.hasNext()) {
      sessionName = (String) names.next();
      session = getSessionForName(sessionName);
      historicalBroker.registerSession(sessionName, session.acquireHistoricalSession(clause));
    }
    return historicalBroker;
  }
 /**
  * Commit changed of the objects of the class type in the change set. This allows for the order of
  * the classes to be processed optimally.
  */
 protected void commitChangedObjectsForClassWithChangeSet(
     UnitOfWorkChangeSet uowChangeSet, Class theClass) {
   Map<ObjectChangeSet, ObjectChangeSet> objectChangesList =
       uowChangeSet.getObjectChanges().get(theClass);
   if (objectChangesList != null) { // may be no changes for that class type.		
     ClassDescriptor descriptor = null;
     AbstractSession session = getSession();
     Collection<ObjectChangeSet> changes = objectChangesList.values();
     if (((UnitOfWorkImpl) session).shouldOrderUpdates()) {
       changes = new ArrayList(objectChangesList.values());
       Collections.sort((List) changes);
     }
     for (ObjectChangeSet changeSetToWrite : changes) {
       Object objectToWrite = changeSetToWrite.getUnitOfWorkClone();
       if (descriptor == null) {
         descriptor = session.getDescriptor(objectToWrite);
       }
       if (!isProcessedCommit(objectToWrite)) {
         // Commit and resume on failure can cause a new change set to be in existing, so need to
         // check here.
         WriteObjectQuery commitQuery = null;
         if (changeSetToWrite.isNew()) {
           commitQuery = new InsertObjectQuery();
         } else {
           commitQuery = new UpdateObjectQuery();
         }
         commitQuery.setIsExecutionClone(true);
         commitQuery.setDescriptor(descriptor);
         commitQuery.setObjectChangeSet(changeSetToWrite);
         commitQuery.setObject(objectToWrite);
         commitQuery.cascadeOnlyDependentParts();
         // removed checking session type to set cascade level
         // will always be a unitOfWork so we need to cascade dependent parts
         session.executeQuery(commitQuery);
       }
     }
   }
 }
  /** INTERNAL: Return the implementor for a specified type */
  protected Object getImplementorForType(Object type, AbstractSession session) {
    if (type == null) {
      return getTypeIndicatorTranslation().get(Helper.getNullWrapper());
    }

    // Must ensure the type is the same, i.e. Integer != BigDecimal.
    try {
      type = session.getDatasourcePlatform().convertObject(type, getTypeField().getType());
    } catch (ConversionException e) {
      throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
    }

    return getTypeIndicatorTranslation().get(type);
  }
 // bug 331064 - Sort the delete order based on PKs.
 private List sort(Class theClass, List objects) {
   ClassDescriptor descriptor = session.getDescriptor(theClass);
   org.eclipse.persistence.internal.descriptors.ObjectBuilder objectBuilder =
       descriptor.getObjectBuilder();
   int size = objects.size();
   TreeMap sortedObjects = new TreeMap();
   for (int index = 0; index < size; index++) {
     Object objectToDelete = objects.get(index);
     if (objectToDelete.getClass() == theClass) {
       sortedObjects.put(
           objectBuilder.extractPrimaryKeyFromObject(objectToDelete, session), objectToDelete);
     }
   }
   return new ArrayList(sortedObjects.values());
 }
  /** INTERNAL: Initialize the mapping. */
  public void initialize(AbstractSession session) throws DescriptorException {
    setReferenceDescriptor(session.getDescriptor(getReferenceClass()));

    if (referenceDescriptor == null) {
      throw DescriptorException.descriptorIsMissing(getReferenceClass().getName(), this);
    }

    // For bug 2730536 convert the field to be an ObjectRelationalDatabaseField.
    ObjectRelationalDatabaseField field = (ObjectRelationalDatabaseField) getField();
    field.setSqlType(java.sql.Types.REF);
    if (referenceDescriptor instanceof ObjectRelationalDataTypeDescriptor) {
      field.setSqlTypeName(
          ((ObjectRelationalDataTypeDescriptor) referenceDescriptor).getStructureName());
    }

    setField(getDescriptor().buildField(getField()));
    setFields(collectFields());

    // Ref mapping requires native connection in WLS as the Ref is wrapped.
    getDescriptor().setIsNativeConnectionRequired(true);
  }
  /**
   * INTERNAL: Get a value from the object and set that in the respective field of the row. If the
   * mapping id target foreign key, you must only write the type into the roe, the rest will be
   * updated when the object itself is written
   */
  @Override
  public void writeFromObjectIntoRowWithChangeRecord(
      ChangeRecord changeRecord, AbstractRecord record, AbstractSession session) {
    if (isReadOnly()) {
      return;
    }

    ObjectChangeSet changeSet =
        (ObjectChangeSet) ((ObjectReferenceChangeRecord) changeRecord).getNewValue();
    if (changeSet == null) {
      writeFromNullObjectIntoRow(record);
    } else {
      Object referenceObject = changeSet.getUnitOfWorkClone();
      if (isForeignKeyRelationship()) {
        Enumeration sourceFields = getForeignKeyFields().elements();
        ClassDescriptor descriptor = session.getDescriptor(referenceObject.getClass());
        while (sourceFields.hasMoreElements()) {
          DatabaseField sourceKey = (DatabaseField) sourceFields.nextElement();
          String targetQueryKey = (String) getSourceToTargetQueryKeyNames().get(sourceKey);
          DatabaseField targetKeyField =
              descriptor.getObjectBuilder().getFieldForQueryKeyName(targetQueryKey);
          if (targetKeyField == null) {
            throw DescriptorException.variableOneToOneMappingIsNotDefinedProperly(
                this, descriptor, targetQueryKey);
          }
          Object referenceValue =
              descriptor
                  .getObjectBuilder()
                  .extractValueFromObjectForField(referenceObject, targetKeyField, session);
          record.put(sourceKey, referenceValue);
        }
      }
      if (getTypeField() != null) {
        record.put(getTypeField(), getTypeForImplementor(referenceObject.getClass()));
      }
    }
  }
 /** INTERNAL: Begin the transaction on all child sessions. */
 protected void basicBeginTransaction() throws DatabaseException {
   for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
     AbstractSession session = (AbstractSession) sessionEnum.next();
     session.beginTransaction();
   }
 }
  /**
   * INTERNAL: Gets the session which this query will be executed on. Generally will be called
   * immediately before the call is translated, which is immediately before session.executeCall.
   *
   * <p>Since the execution session also knows the correct datasource platform to execute on, it is
   * often used in the mappings where the platform is needed for type conversion, or where calls are
   * translated.
   *
   * <p>Is also the session with the accessor. Will return a ClientSession if it is in transaction
   * and has a write connection.
   *
   * @return a session with a live accessor
   * @param query may store session name or reference class for brokers case
   */
  public AbstractSession getExecutionSession(DatabaseQuery query) {
    AbstractSession sessionByQuery = getSessionForQuery(query);

    // Always forward to a registered session.
    return sessionByQuery.getExecutionSession(query);
  }
 /**
  * INTERNAL: Return a descriptor for the target of this mapping For normal
  * ObjectReferenceMappings, we return the reference descriptor. For a VariableOneToOneMapping, the
  * reference descriptor is often a descriptor for an interface and does not contain adequate
  * information. As a result, we look up the descriptor for the specific class we are looking for
  * Bug 2612571
  */
 @Override
 public ClassDescriptor getDescriptorForTarget(Object targetObject, AbstractSession session) {
   return session.getDescriptor(targetObject);
 }
 /**
  * INTERNAL: Called in the end of beforeCompletion of external transaction sychronization
  * listener. Close the managed sql connection corresponding to the external transaction, if
  * applicable releases accessor.
  */
 public void releaseJTSConnection() {
   for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
     AbstractSession session = (AbstractSession) sessionEnum.next();
     session.releaseJTSConnection();
   }
 }
 /** INTERNAL: */
 @Override
 protected Object getPrimaryKeyForObject(Object object, AbstractSession session) {
   return session.getId(object);
 }