use of org.hibernate.LockOptions in project hibernate-orm by hibernate.
the class CriteriaQueryTranslator method getQueryParameters.
public QueryParameters getQueryParameters() {
final RowSelection selection = new RowSelection();
selection.setFirstRow(rootCriteria.getFirstResult());
selection.setMaxRows(rootCriteria.getMaxResults());
selection.setTimeout(rootCriteria.getTimeout());
selection.setFetchSize(rootCriteria.getFetchSize());
final LockOptions lockOptions = new LockOptions();
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()) {
final CriteriaImpl.Subcriteria subcriteria = subcriteriaIterator.next();
final LockMode lm = subcriteria.getLockMode();
if (lm != null) {
lockOptions.setAliasSpecificLockMode(getSQLAlias(subcriteria), lm);
}
if (subcriteria.getWithClause() != null) {
final 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).
final Iterator<CriteriaImpl.CriterionEntry> iter = rootCriteria.iterateExpressionEntries();
while (iter.hasNext()) {
final CriteriaImpl.CriterionEntry ce = iter.next();
final TypedValue[] tv = ce.getCriterion().getTypedValues(ce.getCriteria(), this);
for (TypedValue aTv : tv) {
values.add(aTv.getValue());
types.add(aTv.getType());
}
}
final Object[] valueArray = values.toArray();
final 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());
}
use of org.hibernate.LockOptions in project hibernate-orm by hibernate.
the class CustomLoader method applyLocks.
@Override
protected String applyLocks(String sql, QueryParameters parameters, Dialect dialect, List<AfterLoadAction> afterLoadActions) throws QueryException {
final LockOptions lockOptions = parameters.getLockOptions();
if (lockOptions == null || (lockOptions.getLockMode() == LockMode.NONE && lockOptions.getAliasLockCount() == 0)) {
return sql;
}
// user is request locking, lets see if we can apply locking directly to the SQL...
// some dialects wont allow locking with paging...
afterLoadActions.add(new AfterLoadAction() {
private final LockOptions originalLockOptions = lockOptions.makeCopy();
@Override
public void afterLoad(SharedSessionContractImplementor session, Object entity, Loadable persister) {
((Session) session).buildLockRequest(originalLockOptions).lock(persister.getEntityName(), entity);
}
});
parameters.getLockOptions().setLockMode(LockMode.READ);
return sql;
}
use of org.hibernate.LockOptions in project hibernate-orm by hibernate.
the class AbstractLoadPlanBasedLoader method prepareQueryStatement.
/**
* Obtain a <tt>PreparedStatement</tt> with all parameters pre-bound.
* Bind JDBC-style <tt>?</tt> parameters, named parameters, and
* limit parameters.
*/
protected final PreparedStatement prepareQueryStatement(final String sql, final QueryParameters queryParameters, final LimitHandler limitHandler, final boolean scroll, final SharedSessionContractImplementor session) throws SQLException, HibernateException {
final Dialect dialect = session.getJdbcServices().getJdbcEnvironment().getDialect();
final RowSelection selection = queryParameters.getRowSelection();
final boolean useLimit = LimitHelper.useLimit(limitHandler, selection);
final boolean hasFirstRow = LimitHelper.hasFirstRow(selection);
final boolean useLimitOffset = hasFirstRow && useLimit && limitHandler.supportsLimitOffset();
final boolean callable = queryParameters.isCallable();
final ScrollMode scrollMode = getScrollMode(scroll, hasFirstRow, useLimitOffset, queryParameters);
final PreparedStatement st = session.getJdbcCoordinator().getStatementPreparer().prepareQueryStatement(sql, callable, scrollMode);
try {
int col = 1;
//TODO: can we limit stored procedures ?!
col += limitHandler.bindLimitParametersAtStartOfQuery(selection, st, col);
if (callable) {
col = dialect.registerResultSetOutParameter((CallableStatement) st, col);
}
col += bindParameterValues(st, queryParameters, col, session);
col += limitHandler.bindLimitParametersAtEndOfQuery(selection, st, col);
limitHandler.setMaxRows(selection, st);
if (selection != null) {
if (selection.getTimeout() != null) {
st.setQueryTimeout(selection.getTimeout());
}
if (selection.getFetchSize() != null) {
st.setFetchSize(selection.getFetchSize());
}
}
// handle lock timeout...
final LockOptions lockOptions = queryParameters.getLockOptions();
if (lockOptions != null) {
if (lockOptions.getTimeOut() != LockOptions.WAIT_FOREVER) {
if (!dialect.supportsLockTimeouts()) {
if (log.isDebugEnabled()) {
log.debugf("Lock timeout [%s] requested but dialect reported to not support lock timeouts", lockOptions.getTimeOut());
}
} else if (dialect.isLockTimeoutParameterized()) {
st.setInt(col++, lockOptions.getTimeOut());
}
}
}
if (log.isTraceEnabled()) {
log.tracev("Bound [{0}] parameters total", col);
}
} catch (SQLException sqle) {
session.getJdbcCoordinator().getResourceRegistry().release(st);
session.getJdbcCoordinator().afterStatementExecution();
throw sqle;
} catch (HibernateException he) {
session.getJdbcCoordinator().getResourceRegistry().release(st);
session.getJdbcCoordinator().afterStatementExecution();
throw he;
}
return st;
}
use of org.hibernate.LockOptions in project hibernate-orm by hibernate.
the class DynamicBatchingEntityLoaderBuilder method performUnorderedMultiLoad.
@SuppressWarnings("unchecked")
protected List performUnorderedMultiLoad(OuterJoinLoadable persister, Serializable[] ids, SharedSessionContractImplementor session, MultiLoadOptions loadOptions) {
assert !loadOptions.isOrderReturnEnabled();
final List result = CollectionHelper.arrayList(ids.length);
if (loadOptions.isSessionCheckingEnabled()) {
// the user requested that we exclude ids corresponding to already managed
// entities from the generated load SQL. So here we will iterate all
// incoming id values and see whether it corresponds to an existing
// entity associated with the PC - if it does we add it to the result
// list immediately and remove its id from the group of ids to load.
boolean foundAnyManagedEntities = false;
final List<Serializable> nonManagedIds = new ArrayList<Serializable>();
for (Serializable id : ids) {
final EntityKey entityKey = new EntityKey(id, persister);
final Object managedEntity = session.getPersistenceContext().getEntity(entityKey);
if (managedEntity != null) {
if (!loadOptions.isReturnOfDeletedEntitiesEnabled()) {
final EntityEntry entry = session.getPersistenceContext().getEntry(managedEntity);
if (entry.getStatus() == Status.DELETED || entry.getStatus() == Status.GONE) {
continue;
}
}
foundAnyManagedEntities = true;
result.add(managedEntity);
} else {
nonManagedIds.add(id);
}
}
if (foundAnyManagedEntities) {
if (nonManagedIds.isEmpty()) {
// all of the given ids were already associated with the Session
return result;
} else {
// over-write the ids to be loaded with the collection of
// just non-managed ones
ids = nonManagedIds.toArray((Serializable[]) Array.newInstance(ids.getClass().getComponentType(), nonManagedIds.size()));
}
}
}
final LockOptions lockOptions = (loadOptions.getLockOptions() == null) ? new LockOptions(LockMode.NONE) : loadOptions.getLockOptions();
int numberOfIdsLeft = ids.length;
final int maxBatchSize;
if (loadOptions.getBatchSize() != null && loadOptions.getBatchSize() > 0) {
maxBatchSize = loadOptions.getBatchSize();
} else {
maxBatchSize = session.getJdbcServices().getJdbcEnvironment().getDialect().getDefaultBatchLoadSizingStrategy().determineOptimalBatchLoadSize(persister.getIdentifierType().getColumnSpan(session.getFactory()), numberOfIdsLeft);
}
int idPosition = 0;
while (numberOfIdsLeft > 0) {
int batchSize = Math.min(numberOfIdsLeft, maxBatchSize);
final DynamicEntityLoader batchingLoader = new DynamicEntityLoader(persister, batchSize, lockOptions, session.getFactory(), session.getLoadQueryInfluencers());
Serializable[] idsInBatch = new Serializable[batchSize];
System.arraycopy(ids, idPosition, idsInBatch, 0, batchSize);
QueryParameters qp = buildMultiLoadQueryParameters(persister, idsInBatch, lockOptions);
result.addAll(batchingLoader.doEntityBatchFetch(session, qp, idsInBatch));
numberOfIdsLeft = numberOfIdsLeft - batchSize;
idPosition += batchSize;
}
return result;
}
use of org.hibernate.LockOptions in project hibernate-orm by hibernate.
the class QueryLoader method applyLocks.
@Override
protected String applyLocks(String sql, QueryParameters parameters, Dialect dialect, List<AfterLoadAction> afterLoadActions) throws QueryException {
// can't cache this stuff either (per-invocation)
// we are given a map of user-alias -> lock mode
// create a new map of sql-alias -> lock mode
final LockOptions lockOptions = parameters.getLockOptions();
if (lockOptions == null || (lockOptions.getLockMode() == LockMode.NONE && lockOptions.getAliasLockCount() == 0)) {
return sql;
}
// some dialects wont allow locking with paging...
if (shouldUseFollowOnLocking(parameters, dialect, afterLoadActions)) {
return sql;
}
// there are other conditions we might want to add here, such as checking the result types etc
// but those are better served afterQuery we have redone the SQL generation to use ASTs.
// we need both the set of locks and the columns to reference in locks
// as the ultimate output of this section...
final LockOptions locks = new LockOptions(lockOptions.getLockMode());
final Map<String, String[]> keyColumnNames = dialect.forUpdateOfColumns() ? new HashMap<>() : null;
locks.setScope(lockOptions.getScope());
locks.setTimeOut(lockOptions.getTimeOut());
for (Map.Entry<String, String> entry : sqlAliasByEntityAlias.entrySet()) {
final String userAlias = entry.getKey();
final String drivingSqlAlias = entry.getValue();
if (drivingSqlAlias == null) {
throw new IllegalArgumentException("could not locate alias to apply lock mode : " + userAlias);
}
// at this point we have (drivingSqlAlias) the SQL alias of the driving table
// corresponding to the given user alias. However, the driving table is not
// (necessarily) the table against which we want to apply locks. Mainly,
// the exception case here is joined-subclass hierarchies where we instead
// want to apply the lock against the root table (for all other strategies,
// it just happens that driving and root are the same).
final QueryNode select = (QueryNode) queryTranslator.getSqlAST();
final Lockable drivingPersister = (Lockable) select.getFromClause().findFromElementByUserOrSqlAlias(userAlias, drivingSqlAlias).getQueryable();
final String sqlAlias = drivingPersister.getRootTableAlias(drivingSqlAlias);
final LockMode effectiveLockMode = lockOptions.getEffectiveLockMode(userAlias);
locks.setAliasSpecificLockMode(sqlAlias, effectiveLockMode);
if (keyColumnNames != null) {
keyColumnNames.put(sqlAlias, drivingPersister.getRootTableIdentifierColumnNames());
}
}
// apply the collected locks and columns
return dialect.applyLocksToSql(sql, locks, keyColumnNames);
}
Aggregations