loader.java
来自「hibernate-3.0.5 中文文档」· Java 代码 · 共 1,696 行 · 第 1/4 页
JAVA
1,696 行
} } if ( log.isTraceEnabled() ) log.trace( "done processing result set (" + count + " rows)" ); } finally { session.getBatcher().closeQueryStatement( st, rs ); } initializeEntitiesAndCollections( hydratedObjects, rs, session, queryParameters.isReadOnly() ); if ( createSubselects ) createSubselects( subselectResultKeys, queryParameters, session ); return results; //getResultList(results); } protected boolean isSubselectLoadingEnabled() { return false; } protected boolean hasSubselectLoadableCollections() { final Loadable[] loadables = getEntityPersisters(); for (int i=0; i<loadables.length; i++ ) { if ( loadables[i].hasSubselectLoadableCollections() ) return true; } return false; } private static Set[] transpose( List keys ) { Set[] result = new Set[ ( ( EntityKey[] ) keys.get(0) ).length ]; for ( int j=0; j<result.length; j++ ) { result[j] = new HashSet( keys.size() ); for ( int i=0; i<keys.size(); i++ ) { result[j].add( ( ( EntityKey[] ) keys.get(i) ) [j] ); } } return result; } private void createSubselects(List keys, QueryParameters queryParameters, SessionImplementor session) { if ( keys.size() > 1 ) { //if we only returned one entity, query by key is more efficient Set[] keySets = transpose(keys); final Loadable[] loadables = getEntityPersisters(); final String[] aliases = getAliases(); final Iterator iter = keys.iterator(); while ( iter.hasNext() ) { final EntityKey[] rowKeys = (EntityKey[]) iter.next(); for ( int i=0; i<rowKeys.length; i++ ) { if ( rowKeys[i]!=null && loadables[i].hasSubselectLoadableCollections() ) { SubselectFetch subselectFetch = new SubselectFetch( //getSQLString(), aliases[i], loadables[i], queryParameters, keySets[i] ); session.getPersistenceContext() .getBatchFetchQueue() .addSubselect( rowKeys[i], subselectFetch ); } } } } } private void initializeEntitiesAndCollections( final List hydratedObjects, final Object resultSetId, final SessionImplementor session, final boolean readOnly) throws HibernateException { //important: reuse the same event instances for performance! final PreLoadEvent pre = new PreLoadEvent(session); final PostLoadEvent post = new PostLoadEvent(session); final CollectionPersister[] collectionPersisters = getCollectionPersisters(); if ( collectionPersisters != null ) { for ( int i=0; i<collectionPersisters.length; i++ ) { if ( collectionPersisters[i].isArray() ) { //for arrays, we should end the collection load before resolving //the entities, since the actual array instances are not instantiated //during loading //TODO: or we could do this polymorphically, and have two // different operations implemented differently for arrays endCollectionLoad( resultSetId, session, collectionPersisters[i] ); } } } if ( getEntityPersisters().length > 0 ) { //if no persisters, hydratedObjects is null int hydratedObjectsSize = hydratedObjects.size(); if ( log.isTraceEnabled() ) log.trace( "total objects hydrated: " + hydratedObjectsSize ); for ( int i = 0; i < hydratedObjectsSize; i++ ) { TwoPhaseLoad.initializeEntity( hydratedObjects.get(i), readOnly, session, pre, post ); } } if ( collectionPersisters != null ) { for ( int i=0; i<collectionPersisters.length; i++ ) { if ( !collectionPersisters[i].isArray() ) { //for sets, we should end the collection load after resolving //the entities, since we might call hashCode() on the elements //TODO: or we could do this polymorphically, and have two // different operations implemented differently for arrays endCollectionLoad( resultSetId, session, collectionPersisters[i] ); } } } } private void endCollectionLoad( final Object resultSetId, final SessionImplementor session, final CollectionPersister collectionPersister ) { //this is a query and we are loading multiple instances of the same collection role session.getPersistenceContext().getCollectionLoadContext() .endLoadingCollections( collectionPersister, resultSetId, session ); } protected List getResultList(List results) throws QueryException { return results; } /** * Get the actual object that is returned in the user-visible result list. * This empty implementation merely returns its first argument. This is * overridden by some subclasses. */ protected Object getResultColumnOrRow(Object[] row, ResultSet rs, SessionImplementor session) throws SQLException, HibernateException { return row; } /** * For missing objects associated by one-to-one with another object in the * result set, register the fact that the the object is missing with the * session. */ private void registerNonExists(final EntityKey[] keys, final Loadable[] persisters, final SessionImplementor session) { final int[] owners = getOwners(); if ( owners != null ) { EntityType[] ownerAssociationTypes = getOwnerAssociationTypes(); for ( int i = 0; i < keys.length; i++ ) { int owner = owners[i]; if ( owner > -1 ) { EntityKey ownerKey = keys[owner]; if ( keys[i] == null && ownerKey != null ) { final PersistenceContext persistenceContext = session.getPersistenceContext(); /*final boolean isPrimaryKey; final boolean isSpecialOneToOne; if ( ownerAssociationTypes == null || ownerAssociationTypes[i] == null ) { isPrimaryKey = true; isSpecialOneToOne = false; } else { isPrimaryKey = ownerAssociationTypes[i].getRHSUniqueKeyPropertyName()==null; isSpecialOneToOne = ownerAssociationTypes[i].getLHSPropertyName()!=null; }*/ //TODO: can we *always* use the "null property" approach for everything? /*if ( isPrimaryKey && !isSpecialOneToOne ) { persistenceContext.addNonExistantEntityKey( new EntityKey( ownerKey.getIdentifier(), persisters[i], session.getEntityMode() ) ); } else if ( isSpecialOneToOne ) {*/ boolean isOneToOneAssociation = ownerAssociationTypes!=null && ownerAssociationTypes[i]!=null && ownerAssociationTypes[i].isOneToOne(); if ( isOneToOneAssociation ) { persistenceContext.addNullProperty( ownerKey, ownerAssociationTypes[i].getPropertyName() ); } /*} else { persistenceContext.addNonExistantEntityUniqueKey( new EntityUniqueKey( persisters[i].getEntityName(), ownerAssociationTypes[i].getRHSUniqueKeyPropertyName(), ownerKey.getIdentifier(), persisters[owner].getIdentifierType(), session.getEntityMode() ) ); }*/ } } } } } /** * Read one collection element from the current row of the JDBC result set */ private void readCollectionElement(final Object optionalOwner, final Serializable optionalKey, final CollectionPersister persister, final CollectionAliases descriptor, final ResultSet rs, final SessionImplementor session) throws HibernateException, SQLException { final PersistenceContext persistenceContext = session.getPersistenceContext(); final Serializable collectionRowKey = (Serializable) persister.readKey( rs, descriptor.getSuffixedKeyAliases(), session ); if ( collectionRowKey != null ) { // we found a collection element in the result set if ( log.isDebugEnabled() ) { log.debug( "found row of collection: " + MessageHelper.collectionInfoString( persister, collectionRowKey, getFactory() ) ); } Object owner = optionalOwner; if ( owner == null ) { owner = persistenceContext.getCollectionOwner( collectionRowKey, persister ); if ( owner == null ) { //TODO: This is assertion is disabled because there is a bug that means the // original owner of a transient, uninitialized collection is not known // if the collection is re-referenced by a different object associated // with the current Session //throw new AssertionFailure("bug loading unowned collection"); } } PersistentCollection rowCollection = persistenceContext.getCollectionLoadContext() .getLoadingCollection( persister, collectionRowKey, rs, session.getEntityMode() ); if ( rowCollection != null ) { rowCollection.readFrom( rs, persister, descriptor, owner ); } } else if ( optionalKey != null ) { // we did not find a collection element in the result set, so we // ensure that a collection is created with the owner's identifier, // since what we have is an empty collection if ( log.isDebugEnabled() ) { log.debug( "result set contains (possibly empty) collection: " + MessageHelper.collectionInfoString( persister, optionalKey, getFactory() ) ); } persistenceContext.getCollectionLoadContext() .getLoadingCollection( persister, optionalKey, rs, session.getEntityMode() ); //handle empty collection } // else no collection element, but also no owner } /** * If this is a collection initializer, we need to tell the session that a collection * is being initilized, to account for the possibility of the collection having * no elements (hence no rows in the result set). */ private void handleEmptyCollections(final Serializable[] keys, final Object resultSetId, final SessionImplementor session) throws HibernateException { if ( keys != null ) { // this is a collection initializer, so we must create a collection // for each of the passed-in keys, to account for the possibility // that the collection is empty and has no rows in the result set CollectionPersister[] collectionPersisters = getCollectionPersisters(); for ( int j=0; j<collectionPersisters.length; j++ ) { for ( int i = 0; i < keys.length; i++ ) { //handle empty collections if ( log.isDebugEnabled() ) { log.debug( "result set contains (possibly empty) collection: " + MessageHelper.collectionInfoString( collectionPersisters[j], keys[i], getFactory() ) ); } session.getPersistenceContext() .getCollectionLoadContext() .getLoadingCollection( collectionPersisters[j], keys[i], resultSetId, session.getEntityMode() ); } } } // else this is not a collection initializer (and empty collections will // be detected by looking for the owner's identifier in the result set) } /** * Read a row of <tt>Key</tt>s from the <tt>ResultSet</tt> into the given array. * Warning: this method is side-effecty. * <p/> * If an <tt>id</tt> is given, don't bother going to the <tt>ResultSet</tt>. */ private EntityKey getKeyFromResultSet(final int i, final Loadable persister, final Serializable id, final ResultSet rs, final SessionImplementor session) throws HibernateException, SQLException { Serializable resultId; // if we know there is exactly 1 row, we can skip. // it would be great if we could _always_ skip this; // it is a problem for <key-many-to-one> if ( isSingleRowLoader() && id != null ) { resultId = id; } else { Type idType = persister.getIdentifierType(); resultId = (Serializable) idType.nullSafeGet( rs, getEntityAliases()[i].getSuffixedKeyAliases(), session, null //problematic for <key-many-to-one>! ); final boolean idIsResultId = id != null && resultId != null && idType.isEqual( id, resultId, session.getEntityMode(), factory ); if ( idIsResultId ) resultId = id; //use the id passed in } return resultId == null ? null : new EntityKey( resultId, persister, session.getEntityMode() ); } /** * Check the version of the object in the <tt>ResultSet</tt> against * the object version in the session cache, throwing an exception * if the version numbers are different */ private void checkVersion(final int i, final Loadable persister, final Serializable id, final Object entity, final ResultSet rs, final SessionImplementor session) throws HibernateException, SQLException { Object version = session.getPersistenceContext().getEntry( entity ).getVersion(); if ( version != null ) { //null version means the object is in the process of being loaded somewhere else in the ResultSet VersionType versionType = persister.getVersionType(); Object currentVersion = versionType.nullSafeGet( rs, getEntityAliases()[i].getSuffixedVersionAliases(), session, null ); if ( !versionType.isEqual(version, currentVersion) ) { throw new StaleObjectStateException( persister.getEntityName(), id ); } } } /** * Resolve any ids for currently loaded objects, duplications within the * <tt>ResultSet</tt>, etc. Instantiate empty objects to be initialized from the * <tt>ResultSet</tt>. Return an array of objects (a row of results) and an * array of booleans (by side-effect) that determine whether the corresponding * object should be initialized. */ private Object[] getRow(final ResultSet rs, final Loadable[] persisters, final EntityKey[] keys, final Object optionalObject, final EntityKey optionalObjectKey, final LockMode[] lockModes, final List hydratedObjects, final SessionImplementor session) throws HibernateException, SQLException { final int cols = persisters.length; final EntityAliases[] descriptors = getEntityAliases(); if ( log.isDebugEnabled() ) log.debug( "result row: " + StringHelper.toString( keys ) ); final Object[] rowResults = new Object[cols]; for ( int i = 0; i < cols; i++ ) { Object object = null; EntityKey key = keys[i]; if ( keys[i] == null ) { //do nothing } else { //If the object is already loaded, return the loaded one object = session.getEntityUsingInterceptor( key ); if ( object != null ) { //its already loaded so don't need to hydrate it instanceAlreadyLoaded( rs, i, persisters[i],
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?