📄 loader.java
字号:
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() .getLoadContexts() .getCollectionLoadContext( ( ResultSet ) resultSetId ) .endLoadingCollections( collectionPersister ); } protected List getResultList(List results, ResultTransformer resultTransformer) 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, ResultTransformer transformer, 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.getLoadContexts() .getCollectionLoadContext( rs ) .getLoadingCollection( persister, collectionRowKey ); 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.getLoadContexts() .getCollectionLoadContext( rs ) .getLoadingCollection( persister, optionalKey ); // 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) { 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() .getLoadContexts() .getCollectionLoadContext( ( ResultSet ) resultSetId ) .getLoadingCollection( collectionPersisters[j], keys[i] ); } } } // 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) ) { if ( session.getFactory().getStatistics().isStatisticsEnabled() ) { session.getFactory().getStatisticsImplementor() .optimisticFailure( persister.getEntityName() ); } 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], key, object, lockModes[i], session ); } else { object = instanceNotYetLoaded( rs, i, persisters[i], descriptors[i].getRowIdAlias(), key, lockModes[i], optionalObjectKey, optionalObject, hydratedObjects, session ); } } rowResults[i] = object; } return rowResults; } /** * The entity instance is already in the session cache */ private void instanceAlreadyLoaded( final ResultSet rs, final int i, final Loadable persister, final EntityKey key, final Object object, final LockMode lockMode, final SessionImplementor session) throws HibernateException, SQLException { if ( !persister.isInstance( object, session.getEntityMode() ) ) { throw new WrongClassException( "loaded object was of wrong class " + object.getClass(), key.getIdentifier(), persister.getEntityName() ); } if ( LockMode.NONE != lockMode && upgradeLocks() ) { //no point doing this if NONE was requested final boolean isVersionCheckNeeded = persister.isVersioned() && session.getPersistenceContext().getEntry(object) .getLockMode().lessThan( lockMode ); // we don't need to worry about existing version being uninitialized // because this block isn't called by a re-entrant load (re-entrant // loads _always_ have lock mode NONE) if (isVersionCheckNeeded) { //we only check the version when _upgrading_ lock modes checkVersion( i, persister, key.getIdentifier(), object, rs, session ); //we need to upgrade the lock mode to the mode requested session.getPersistenceContext().getEntry(object) .setLockMode(lockMode); } } } /** * The entity instance is not in the session cache */ private Object instanceNotYetLoaded( final ResultSet rs, final int i, final Loadable persister, final String rowIdAlias, final EntityKey key, final LockMode lockMode,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -