⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loader.java

📁 好东西,hibernate-3.2.0,他是一开元的树杖hibernate-3.2.0
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
//$Id: Loader.java 10139 2006-07-24 13:19:38Z max.andersen@jboss.com $
package org.hibernate.loader;

import java.io.Serializable;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.QueryException;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.StaleObjectStateException;
import org.hibernate.WrongClassException;
import org.hibernate.cache.FilterKey;
import org.hibernate.cache.QueryCache;
import org.hibernate.cache.QueryKey;
import org.hibernate.collection.PersistentCollection;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.EntityKey;
import org.hibernate.engine.EntityUniqueKey;
import org.hibernate.engine.PersistenceContext;
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.RowSelection;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.SubselectFetch;
import org.hibernate.engine.TwoPhaseLoad;
import org.hibernate.engine.TypedValue;
import org.hibernate.event.EventSource;
import org.hibernate.event.PostLoadEvent;
import org.hibernate.event.PreLoadEvent;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.hql.HolderInstantiator;
import org.hibernate.impl.FetchingScrollableResultsImpl;
import org.hibernate.impl.ScrollableResultsImpl;
import org.hibernate.jdbc.ColumnNameCache;
import org.hibernate.jdbc.ResultSetWrapper;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.entity.UniqueKeyLoadable;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.AssociationType;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
import org.hibernate.type.VersionType;
import org.hibernate.util.StringHelper;

/**
 * Abstract superclass of object loading (and querying) strategies. This class implements
 * useful common functionality that concrete loaders delegate to. It is not intended that this
 * functionality would be directly accessed by client code. (Hence, all methods of this class
 * are declared <tt>protected</tt> or <tt>private</tt>.) This class relies heavily upon the
 * <tt>Loadable</tt> interface, which is the contract between this class and
 * <tt>EntityPersister</tt>s that may be loaded by it.<br>
 * <br>
 * The present implementation is able to load any number of columns of entities and at most
 * one collection role per query.
 *
 * @author Gavin King
 * @see org.hibernate.persister.entity.Loadable
 */
public abstract class Loader {

	private static final Log log = LogFactory.getLog( Loader.class );

	private final SessionFactoryImplementor factory;
	private ColumnNameCache columnNameCache;

	public Loader(SessionFactoryImplementor factory) {
		this.factory = factory;
	}

	/**
	 * The SQL query string to be called; implemented by all subclasses
	 */
	protected abstract String getSQLString();

	/**
	 * An array of persisters of entity classes contained in each row of results;
	 * implemented by all subclasses
	 */
	protected abstract Loadable[] getEntityPersisters();
	
	/**
	 * An array indicating whether the entities have eager property fetching
	 * enabled
	 */
	protected boolean[] getEntityEagerPropertyFetches() {
		return null;
	}

	/**
	 * An array of indexes of the entity that owns a one-to-one association
	 * to the entity at the given index (-1 if there is no "owner")
	 */
	protected int[] getOwners() {
		return null;
	}

	/**
	 * An array of unique key property names by which the corresponding
	 * entities are referenced by other entities in the result set
	 */
	protected EntityType[] getOwnerAssociationTypes() {
		return null;
	}

	/**
	 * An (optional) persister for a collection to be initialized; only 
	 * collection loaders return a non-null value
	 */
	protected CollectionPersister[] getCollectionPersisters() {
		return null;
	}

	/**
	 * Get the index of the entity that owns the collection, or -1
	 * if there is no owner in the query results (ie. in the case of a
	 * collection initializer) or no collection.
	 */
	protected int[] getCollectionOwners() {
		return null;
	}

	/**
	 * What lock mode does this load entities with?
	 *
	 * @param lockModes a collection of lock modes specified dynamically via the Query interface
	 */
	protected abstract LockMode[] getLockModes(Map lockModes);

	/**
	 * Append <tt>FOR UPDATE OF</tt> clause, if necessary. This
	 * empty superclass implementation merely returns its first
	 * argument.
	 */
	protected String applyLocks(String sql, Map lockModes, Dialect dialect) throws HibernateException {
		return sql;
	}

	/**
	 * Does this query return objects that might be already cached
	 * by the session, whose lock mode may need upgrading
	 */
	protected boolean upgradeLocks() {
		return false;
	}

	/**
	 * Return false is this loader is a batch entity loader
	 */
	protected boolean isSingleRowLoader() {
		return false;
	}

	/**
	 * Get the SQL table aliases of entities whose
	 * associations are subselect-loadable, returning
	 * null if this loader does not support subselect
	 * loading
	 */
	protected String[] getAliases() {
		return null;
	}

	/**
	 * Modify the SQL, adding lock hints and comments, if necessary
	 */
	protected String preprocessSQL(String sql, QueryParameters parameters, Dialect dialect)
			throws HibernateException {
		
		sql = applyLocks( sql, parameters.getLockModes(), dialect );
		
		return getFactory().getSettings().isCommentsEnabled() ?
				prependComment( sql, parameters ) : sql;
	}

	private String prependComment(String sql, QueryParameters parameters) {
		String comment = parameters.getComment();
		if ( comment == null ) {
			return sql;
		}
		else {
			return new StringBuffer( comment.length() + sql.length() + 5 )
					.append( "/* " )
					.append( comment )
					.append( " */ " )
					.append( sql )
					.toString();
		}
	}

	/**
	 * Execute an SQL query and attempt to instantiate instances of the class mapped by the given
	 * persister from each row of the <tt>ResultSet</tt>. If an object is supplied, will attempt to
	 * initialize that object. If a collection is supplied, attempt to initialize that collection.
	 */
	private List doQueryAndInitializeNonLazyCollections(final SessionImplementor session,
														final QueryParameters queryParameters,
														final boolean returnProxies) 
		throws HibernateException, SQLException {

		final PersistenceContext persistenceContext = session.getPersistenceContext();
		persistenceContext.beforeLoad();
		List result;
		try {
			result = doQuery( session, queryParameters, returnProxies );
		}
		finally {
			persistenceContext.afterLoad();
		}
		persistenceContext.initializeNonLazyCollections();
		return result;
	}

	/**
	 * Loads a single row from the result set.  This is the processing used from the
	 * ScrollableResults where no collection fetches were encountered.
	 *
	 * @param resultSet The result set from which to do the load.
	 * @param session The session from which the request originated.
	 * @param queryParameters The query parameters specified by the user.
	 * @param returnProxies Should proxies be generated
	 * @return The loaded "row".
	 * @throws HibernateException
	 */
	public Object loadSingleRow(
	        final ResultSet resultSet,
	        final SessionImplementor session,
	        final QueryParameters queryParameters,
	        final boolean returnProxies) throws HibernateException {

		final int entitySpan = getEntityPersisters().length;
		final List hydratedObjects = entitySpan == 0 ? 
				null : new ArrayList( entitySpan );

		final Object result;
		try {
			result = getRowFromResultSet(
			        resultSet,
					session,
					queryParameters,
					getLockModes( queryParameters.getLockModes() ),
					null,
					hydratedObjects,
					new EntityKey[entitySpan],
					returnProxies
				);
		}
		catch ( SQLException sqle ) {
			throw JDBCExceptionHelper.convert(
			        factory.getSQLExceptionConverter(),
			        sqle,
			        "could not read next row of results",
			        getSQLString()
				);
		}

		initializeEntitiesAndCollections( 
				hydratedObjects, 
				resultSet, 
				session, 
				queryParameters.isReadOnly() 
			);
		session.getPersistenceContext().initializeNonLazyCollections();
		return result;
	}

	private Object sequentialLoad(
	        final ResultSet resultSet,
	        final SessionImplementor session,
	        final QueryParameters queryParameters,
	        final boolean returnProxies,
	        final EntityKey keyToRead) throws HibernateException {

		final int entitySpan = getEntityPersisters().length;
		final List hydratedObjects = entitySpan == 0 ? 
				null : new ArrayList( entitySpan );

		Object result = null;
		final EntityKey[] loadedKeys = new EntityKey[entitySpan];

		try {
			do {
				Object loaded = getRowFromResultSet(
						resultSet,
						session,
						queryParameters,
						getLockModes( queryParameters.getLockModes() ),
						null,
						hydratedObjects,
						loadedKeys,
						returnProxies
					);
				if ( result == null ) {
					result = loaded;
				}
			} 
			while ( keyToRead.equals( loadedKeys[0] ) && resultSet.next() );
		}
		catch ( SQLException sqle ) {
			throw JDBCExceptionHelper.convert(
			        factory.getSQLExceptionConverter(),
			        sqle,
			        "could not perform sequential read of results (forward)",
			        getSQLString()
				);
		}

		initializeEntitiesAndCollections( 
				hydratedObjects, 
				resultSet, 
				session, 
				queryParameters.isReadOnly() 
			);
		session.getPersistenceContext().initializeNonLazyCollections();
		return result;
	}

	/**
	 * Loads a single logical row from the result set moving forward.  This is the
	 * processing used from the ScrollableResults where there were collection fetches
	 * encountered; thus a single logical row may have multiple rows in the underlying
	 * result set.
	 *
	 * @param resultSet The result set from which to do the load.
	 * @param session The session from which the request originated.
	 * @param queryParameters The query parameters specified by the user.
	 * @param returnProxies Should proxies be generated
	 * @return The loaded "row".
	 * @throws HibernateException
	 */
	public Object loadSequentialRowsForward(
	        final ResultSet resultSet,
	        final SessionImplementor session,
	        final QueryParameters queryParameters,
	        final boolean returnProxies) throws HibernateException {

		// note that for sequential scrolling, we make the assumption that
		// the first persister element is the "root entity"

		try {
			if ( resultSet.isAfterLast() ) {
				// don't even bother trying to read further
				return null;
			}

			if ( resultSet.isBeforeFirst() ) {
				resultSet.next();
			}

			// We call getKeyFromResultSet() here so that we can know the
			// key value upon which to perform the breaking logic.  However,
			// it is also then called from getRowFromResultSet() which is certainly
			// not the most efficient.  But the call here is needed, and there
			// currently is no other way without refactoring of the doQuery()/getRowFromResultSet()
			// methods
			final EntityKey currentKey = getKeyFromResultSet(
					0,
					getEntityPersisters()[0],
					null,
					resultSet,
					session
				);

			return sequentialLoad( resultSet, session, queryParameters, returnProxies, currentKey );
		}
		catch ( SQLException sqle ) {
			throw JDBCExceptionHelper.convert(
			        factory.getSQLExceptionConverter(),
			        sqle,
			        "could not perform sequential read of results (forward)",
			        getSQLString()
				);
		}
	}

	/**
	 * Loads a single logical row from the result set moving forward.  This is the
	 * processing used from the ScrollableResults where there were collection fetches
	 * encountered; thus a single logical row may have multiple rows in the underlying
	 * result set.
	 *
	 * @param resultSet The result set from which to do the load.
	 * @param session The session from which the request originated.
	 * @param queryParameters The query parameters specified by the user.
	 * @param returnProxies Should proxies be generated
	 * @return The loaded "row".
	 * @throws HibernateException
	 */
	public Object loadSequentialRowsReverse(
	        final ResultSet resultSet,
	        final SessionImplementor session,
	        final QueryParameters queryParameters,
	        final boolean returnProxies,
	        final boolean isLogicallyAfterLast) throws HibernateException {

		// note that for sequential scrolling, we make the assumption that
		// the first persister element is the "root entity"

		try {
			if ( resultSet.isFirst() ) {
				// don't even bother trying to read any further
				return null;
			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -