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

📄 loader.java

📁 一个Java持久层类库
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
//$Id: Loader.java 11398 2007-04-10 14:54:07Z steve.ebersole@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.slf4j.Logger;import org.slf4j.LoggerFactory;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 Logger log = LoggerFactory.getLogger( 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	 *	 * @return The sql command this loader should use to get its {@link ResultSet}.	 */	protected abstract String getSQLString();	/**	 * An array of persisters of entity classes contained in each row of results;	 * implemented by all subclasses	 *	 * @return The entity persisters.	 */	protected abstract Loadable[] getEntityPersisters();		/**	 * An array indicating whether the entities have eager property fetching	 * enabled.	 *	 * @return Eager property fetching indicators.	 */	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").  The	 * indexes contained here are relative to the result of	 * {@link #getEntityPersisters}.	 *	 * @return The owner indicators (see discussion above).	 */	protected int[] getOwners() {		return null;	}	/**	 * An array of the owner types corresponding to the {@link #getOwners()}	 * returns.  Indices indicating no owner would be null here.	 *	 * @return The types for the owners.	 */	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 {

⌨️ 快捷键说明

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