public QueryParameters getQueryParameters() {
    LockOptions lockOptions = new LockOptions();
    RowSelection selection = new RowSelection();
    selection.setFirstRow(rootCriteria.getFirstResult());
    selection.setMaxRows(rootCriteria.getMaxResults());
    selection.setTimeout(rootCriteria.getTimeout());
    selection.setFetchSize(rootCriteria.getFetchSize());
    final Map<String, LockMode> lockModeMap = rootCriteria.getLockModes();
    for (final String key : lockModeMap.keySet()) {
      final Criteria subcriteria = getAliasedCriteria(key);
      lockOptions.setAliasSpecificLockMode(getSQLAlias(subcriteria), lockModeMap.get(key));
    }
    final List<Object> values = new ArrayList<Object>();
    final List<Type> types = new ArrayList<Type>();
    final Iterator<CriteriaImpl.Subcriteria> subcriteriaIterator =
        rootCriteria.iterateSubcriteria();
    while (subcriteriaIterator.hasNext()) {
      CriteriaImpl.Subcriteria subcriteria = subcriteriaIterator.next();
      LockMode lm = subcriteria.getLockMode();
      if (lm != null) {
        lockOptions.setAliasSpecificLockMode(getSQLAlias(subcriteria), lm);
      }
      if (subcriteria.getWithClause() != null) {
        TypedValue[] tv = subcriteria.getWithClause().getTypedValues(subcriteria, this);
        for (TypedValue aTv : tv) {
          values.add(aTv.getValue());
          types.add(aTv.getType());
        }
      }
    }

    // Type and value gathering for the WHERE clause needs to come AFTER lock mode gathering,
    // because the lock mode gathering loop now contains join clauses which can contain
    // parameter bindings (as in the HQL WITH clause).
    Iterator<CriteriaImpl.CriterionEntry> iter = rootCriteria.iterateExpressionEntries();
    while (iter.hasNext()) {
      CriteriaImpl.CriterionEntry ce = iter.next();
      TypedValue[] tv = ce.getCriterion().getTypedValues(ce.getCriteria(), this);
      for (TypedValue aTv : tv) {
        values.add(aTv.getValue());
        types.add(aTv.getType());
      }
    }

    Object[] valueArray = values.toArray();
    Type[] typeArray = ArrayHelper.toTypeArray(types);
    return new QueryParameters(
        typeArray,
        valueArray,
        lockOptions,
        selection,
        rootCriteria.isReadOnlyInitialized(),
        (rootCriteria.isReadOnlyInitialized() && rootCriteria.isReadOnly()),
        rootCriteria.getCacheable(),
        rootCriteria.getCacheRegion(),
        rootCriteria.getComment(),
        rootCriteria.getQueryHints(),
        rootCriteria.isLookupByNaturalKey(),
        rootCriteria.getResultTransformer());
  }
  public QueryParameters getQueryParameters() {
    LockOptions lockOptions = new LockOptions();
    RowSelection selection = new RowSelection();
    selection.setFirstRow(rootCriteria.getFirstResult());
    selection.setMaxRows(rootCriteria.getMaxResults());
    selection.setTimeout(rootCriteria.getTimeout());
    selection.setFetchSize(rootCriteria.getFetchSize());

    Iterator iter = rootCriteria.getLockModes().entrySet().iterator();
    while (iter.hasNext()) {
      Map.Entry me = (Map.Entry) iter.next();
      final Criteria subcriteria = getAliasedCriteria((String) me.getKey());
      lockOptions.setAliasSpecificLockMode(getSQLAlias(subcriteria), (LockMode) me.getValue());
    }
    List values = new ArrayList();
    List types = new ArrayList();
    iter = rootCriteria.iterateSubcriteria();
    while (iter.hasNext()) {
      CriteriaImpl.Subcriteria subcriteria = (CriteriaImpl.Subcriteria) iter.next();
      LockMode lm = subcriteria.getLockMode();
      if (lm != null) {
        lockOptions.setAliasSpecificLockMode(getSQLAlias(subcriteria), lm);
      }
      if (subcriteria.getWithClause() != null) {
        TypedValue[] tv = subcriteria.getWithClause().getTypedValues(subcriteria, this);
        for (int i = 0; i < tv.length; i++) {
          values.add(tv[i].getValue());
          types.add(tv[i].getType());
        }
      }
    }

    // Type and value gathering for the WHERE clause needs to come AFTER lock mode gathering,
    // because the lock mode gathering loop now contains join clauses which can contain
    // parameter bindings (as in the HQL WITH clause).
    iter = rootCriteria.iterateExpressionEntries();
    while (iter.hasNext()) {
      CriteriaImpl.CriterionEntry ce = (CriteriaImpl.CriterionEntry) iter.next();
      TypedValue[] tv = ce.getCriterion().getTypedValues(ce.getCriteria(), this);
      for (int i = 0; i < tv.length; i++) {
        values.add(tv[i].getValue());
        types.add(tv[i].getType());
      }
    }

    Object[] valueArray = values.toArray();
    Type[] typeArray = ArrayHelper.toTypeArray(types);
    return new QueryParameters(
        typeArray,
        valueArray,
        lockOptions,
        selection,
        rootCriteria.isReadOnlyInitialized(),
        (rootCriteria.isReadOnlyInitialized() ? rootCriteria.isReadOnly() : false),
        rootCriteria.getCacheable(),
        rootCriteria.getCacheRegion(),
        rootCriteria.getComment(),
        rootCriteria.isLookupByNaturalKey(),
        rootCriteria.getResultTransformer());
  }
 @Override
 protected String applyLocks(
     String sql,
     QueryParameters parameters,
     Dialect dialect,
     List<AfterLoadAction> afterLoadActions)
     throws QueryException {
   // can't cache this stuff either (per-invocation)
   final LockOptions lockOptions = parameters.getLockOptions();
   final String result;
   if (lockOptions == null
       || (lockOptions.getLockMode() == LockMode.NONE && lockOptions.getAliasLockCount() == 0)) {
     return sql;
   } else {
     LockOptions locks = new LockOptions();
     locks.setLockMode(lockOptions.getLockMode());
     locks.setTimeOut(lockOptions.getTimeOut());
     locks.setScope(lockOptions.getScope());
     Iterator iter = lockOptions.getAliasLockIterator();
     while (iter.hasNext()) {
       Map.Entry me = (Map.Entry) iter.next();
       locks.setAliasSpecificLockMode(
           getAliasName((String) me.getKey()), (LockMode) me.getValue());
     }
     Map keyColumnNames = null;
     if (dialect.forUpdateOfColumns()) {
       keyColumnNames = new HashMap();
       for (int i = 0; i < names.length; i++) {
         keyColumnNames.put(names[i], persisters[i].getIdentifierColumnNames());
       }
     }
     result = dialect.applyLocksToSql(sql, locks, keyColumnNames);
   }
   logQuery(queryString, result);
   return result;
 }