Java tutorial
/* * Hibernate, Relational Persistence for Idiomatic Java * * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.loader.criteria; import java.io.Serializable; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.hibernate.HibernateException; import org.hibernate.LockMode; import org.hibernate.LockOptions; import org.hibernate.QueryException; import org.hibernate.ScrollMode; import org.hibernate.Session; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.QueryParameters; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.CriteriaImpl; import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.loader.OuterJoinLoader; import org.hibernate.loader.spi.AfterLoadAction; import org.hibernate.persister.entity.Loadable; import org.hibernate.persister.entity.Lockable; import org.hibernate.persister.entity.OuterJoinLoadable; import org.hibernate.query.spi.ScrollableResultsImplementor; import org.hibernate.transform.ResultTransformer; import org.hibernate.type.Type; /** * A <tt>Loader</tt> for <tt>Criteria</tt> queries. Note that criteria queries are * more like multi-object <tt>load()</tt>s than like HQL queries. * * @author Gavin King */ public class CriteriaLoader extends OuterJoinLoader { //TODO: this class depends directly upon CriteriaImpl, // in the impl package ... add a CriteriaImplementor // interface //NOTE: unlike all other Loaders, this one is NOT // multithreaded, or cacheable!! private final CriteriaQueryTranslator translator; private final Set<Serializable> querySpaces; private final Type[] resultTypes; //the user visible aliases, which are unknown to the superclass, //these are not the actual "physical" SQL aliases private final String[] userAliases; private final boolean[] includeInResultRow; private final int resultRowLength; public CriteriaLoader(final OuterJoinLoadable persister, final SessionFactoryImplementor factory, final CriteriaImpl criteria, final String rootEntityName, final LoadQueryInfluencers loadQueryInfluencers) throws HibernateException { super(factory, loadQueryInfluencers); translator = new CriteriaQueryTranslator(factory, criteria, rootEntityName, CriteriaQueryTranslator.ROOT_SQL_ALIAS); querySpaces = translator.getQuerySpaces(); CriteriaJoinWalker walker = new CriteriaJoinWalker(persister, translator, factory, criteria, rootEntityName, loadQueryInfluencers); initFromWalker(walker); userAliases = walker.getUserAliases(); resultTypes = walker.getResultTypes(); includeInResultRow = walker.includeInResultRow(); resultRowLength = ArrayHelper.countTrue(includeInResultRow); postInstantiate(); } public ScrollableResultsImplementor scroll(SharedSessionContractImplementor session, ScrollMode scrollMode) throws HibernateException { QueryParameters qp = translator.getQueryParameters(); qp.setScrollMode(scrollMode); return scroll(qp, resultTypes, null, session); } public List list(SharedSessionContractImplementor session) throws HibernateException { return list(session, translator.getQueryParameters(), querySpaces, resultTypes); } @Override protected String[] getResultRowAliases() { return userAliases; } @Override protected ResultTransformer resolveResultTransformer(ResultTransformer resultTransformer) { return translator.getRootCriteria().getResultTransformer(); } @Override protected boolean areResultSetRowsTransformedImmediately() { return true; } @Override protected boolean[] includeInResultRow() { return includeInResultRow; } @Override protected Object getResultColumnOrRow(Object[] row, ResultTransformer transformer, ResultSet rs, SharedSessionContractImplementor session) throws SQLException, HibernateException { return resolveResultTransformer(transformer).transformTuple(getResultRow(row, rs, session), getResultRowAliases()); } @Override protected Object[] getResultRow(Object[] row, ResultSet rs, SharedSessionContractImplementor session) throws SQLException, HibernateException { final Object[] result; if (translator.hasProjection()) { Type[] types = translator.getProjectedTypes(); result = new Object[types.length]; String[] columnAliases = translator.getProjectedColumnAliases(); for (int i = 0, pos = 0; i < result.length; i++) { int numColumns = types[i].getColumnSpan(session.getFactory()); if (numColumns > 1) { String[] typeColumnAliases = ArrayHelper.slice(columnAliases, pos, numColumns); result[i] = types[i].nullSafeGet(rs, typeColumnAliases, session, null); } else { result[i] = types[i].nullSafeGet(rs, columnAliases[pos], session, null); } pos += numColumns; } } else { result = toResultRow(row); } return result; } private Object[] toResultRow(Object[] row) { if (resultRowLength == row.length) { return row; } else { Object[] result = new Object[resultRowLength]; int j = 0; for (int i = 0; i < row.length; i++) { if (includeInResultRow[i]) { result[j++] = row[i]; } } return result; } } public Set getQuerySpaces() { return querySpaces; } @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 || (lockOptions.getAliasLockCount() == 1 && lockOptions.getAliasSpecificLockMode("this_") == LockMode.NONE)))) { return sql; } if ((parameters.getLockOptions().getFollowOnLocking() == null && dialect.useFollowOnLocking(parameters)) || (parameters.getLockOptions().getFollowOnLocking() != null && parameters.getLockOptions().getFollowOnLocking())) { final LockMode lockMode = determineFollowOnLockMode(lockOptions); if (lockMode != LockMode.UPGRADE_SKIPLOCKED) { // Dialect prefers to perform locking in a separate step LOG.usingFollowOnLocking(); final LockOptions lockOptionsToUse = new LockOptions(lockMode); lockOptionsToUse.setTimeOut(lockOptions.getTimeOut()); lockOptionsToUse.setScope(lockOptions.getScope()); afterLoadActions.add(new AfterLoadAction() { @Override public void afterLoad(SharedSessionContractImplementor session, Object entity, Loadable persister) { ((Session) session).buildLockRequest(lockOptionsToUse).lock(persister.getEntityName(), entity); } }); parameters.setLockOptions(new LockOptions()); return sql; } } final LockOptions locks = new LockOptions(lockOptions.getLockMode()); locks.setScope(lockOptions.getScope()); locks.setTimeOut(lockOptions.getTimeOut()); final Map<String, String[]> keyColumnNames = dialect.forUpdateOfColumns() ? new HashMap() : null; final String[] drivingSqlAliases = getAliases(); for (int i = 0; i < drivingSqlAliases.length; i++) { final LockMode lockMode = lockOptions.getAliasSpecificLockMode(drivingSqlAliases[i]); if (lockMode != null) { final Lockable drivingPersister = (Lockable) getEntityPersisters()[i]; final String rootSqlAlias = drivingPersister.getRootTableAlias(drivingSqlAliases[i]); locks.setAliasSpecificLockMode(rootSqlAlias, lockMode); if (keyColumnNames != null) { keyColumnNames.put(rootSqlAlias, drivingPersister.getRootTableIdentifierColumnNames()); } } } return dialect.applyLocksToSql(sql, locks, keyColumnNames); } @Override protected LockMode determineFollowOnLockMode(LockOptions lockOptions) { final LockMode lockModeToUse = lockOptions.findGreatestLockMode(); if (lockOptions.getAliasLockCount() > 1) { // > 1 here because criteria always uses alias map for the root lock mode (under 'this_') LOG.aliasSpecificLockingWithFollowOnLocking(lockModeToUse); } return lockModeToUse; } @Override protected LockMode[] getLockModes(LockOptions lockOptions) { final String[] entityAliases = getAliases(); if (entityAliases == null) { return null; } final int size = entityAliases.length; LockMode[] lockModesArray = new LockMode[size]; for (int i = 0; i < size; i++) { LockMode lockMode = lockOptions.getAliasSpecificLockMode(entityAliases[i]); lockModesArray[i] = lockMode == null ? lockOptions.getLockMode() : lockMode; } return lockModesArray; } @Override protected boolean isSubselectLoadingEnabled() { return hasSubselectLoadableCollections(); } @Override protected List getResultList(List results, ResultTransformer resultTransformer) { return resolveResultTransformer(resultTransformer).transformList(results); } @Override protected String getQueryIdentifier() { return "[CRITERIA] " + getSQLString(); } }